@forge-kit/plugin-source-map-prase 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +17 -19
- package/dist/node.js +2552 -0
- package/package.json +5 -3
- package/src/App.less +35 -26
- package/src/App.tsx +70 -23
- package/src/components/map-input-panel/index.less +71 -78
- package/src/components/map-input-panel/index.tsx +19 -20
- package/src/components/panel-card/index.less +16 -13
- package/src/components/panel-card/index.tsx +2 -2
- package/src/components/trace-chain/index.less +119 -120
- package/src/components/trace-chain/index.tsx +9 -7
- package/src/main.tsx +1 -1
- package/src/node/index.ts +6 -0
- package/src/{utils/source-map → node/trace/core}/base/registry.ts +14 -11
- package/src/{utils/source-map → node/trace/core}/base/types.ts +1 -0
- package/src/node/trace/core/domain/chain-slots.ts +33 -0
- package/src/{utils/source-map → node/trace/core}/domain/source-content.ts +15 -2
- package/src/node/trace/core/domain/trace-resolver.ts +179 -0
- package/src/node/trace/core/domain/view-model.ts +57 -0
- package/src/node/trace/resolve/context.ts +59 -0
- package/src/node/trace/resolve/index.ts +97 -0
- package/src/node/trace/resolve/input.ts +35 -0
- package/src/node/trace/resolve/snippet-limit.ts +35 -0
- package/src/node/trace/resolve/types.ts +37 -0
- package/src/node/trace/runner.ts +149 -0
- package/src/shared/trace-common.ts +104 -0
- package/src/shared/trace-contract.ts +29 -0
- package/src/types.ts +11 -0
- package/src/utils/trace-ui/index.ts +12 -0
- package/src/utils/trace-ui/state.ts +81 -0
- package/src/utils/source-map/domain/chain-slots.ts +0 -59
- package/src/utils/source-map/domain/trace-resolver.ts +0 -165
- package/src/utils/source-map/domain/view-model.ts +0 -20
- package/src/utils/source-map/facade/source-map-utils.ts +0 -212
- package/src/utils/source-map/index.ts +0 -18
- /package/src/{utils/source-map → node/trace/core}/base/constants.ts +0 -0
- /package/src/{utils/source-map → node/trace/core}/base/path.ts +0 -0
package/package.json
CHANGED
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
},
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
|
-
"src"
|
|
9
|
+
"src",
|
|
10
|
+
"manifest.json"
|
|
10
11
|
],
|
|
11
12
|
"author": "yu.pan <panyupy@vip.qq.com>",
|
|
12
13
|
"license": "MIT",
|
|
13
|
-
"version": "0.0.
|
|
14
|
+
"version": "0.0.4",
|
|
14
15
|
"type": "module",
|
|
15
16
|
"scripts": {
|
|
16
17
|
"dev": "vite",
|
|
@@ -22,9 +23,10 @@
|
|
|
22
23
|
"@dnd-kit/core": "^6.3.1",
|
|
23
24
|
"@dnd-kit/sortable": "^10.0.0",
|
|
24
25
|
"@dnd-kit/utilities": "^3.2.2",
|
|
26
|
+
"@forge-kit/bridge-client": "workspace:*",
|
|
25
27
|
"@forge-kit/component": "workspace:*",
|
|
26
28
|
"@forge-kit/icons": "workspace:*",
|
|
27
|
-
"@forge-kit/
|
|
29
|
+
"@forge-kit/helper": "workspace:*",
|
|
28
30
|
"classnames": "^2.5.1",
|
|
29
31
|
"react": "^19.2.0",
|
|
30
32
|
"react-dom": "^19.2.0",
|
package/src/App.less
CHANGED
|
@@ -16,46 +16,55 @@ html, body, #root {
|
|
|
16
16
|
overflow: hidden;
|
|
17
17
|
min-height: 0;
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
.top-cards {
|
|
21
20
|
flex: 1;
|
|
22
21
|
min-height: 0;
|
|
22
|
+
|
|
23
|
+
.top-trace-card {
|
|
24
|
+
flex: 1;
|
|
25
|
+
min-height: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.top-input-card {
|
|
29
|
+
flex: 1;
|
|
30
|
+
min-height: 0;
|
|
31
|
+
}
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
.result-panel-card {
|
|
26
35
|
flex: 1;
|
|
27
36
|
min-height: 0;
|
|
28
37
|
display: flex;
|
|
29
|
-
}
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
39
|
+
.result-panel-content {
|
|
40
|
+
flex: 1;
|
|
41
|
+
min-height: 0;
|
|
42
|
+
width: 100%;
|
|
43
|
+
overflow-y: auto;
|
|
44
|
+
overflow-x: hidden;
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
.output-meta {
|
|
47
|
+
margin-bottom: var(--space-2);
|
|
48
|
+
color: var(--gray-11);
|
|
49
|
+
font-size: 12px;
|
|
50
|
+
border: 1px solid var(--gray-6);
|
|
51
|
+
border-radius: 999px;
|
|
52
|
+
padding: 2px 10px;
|
|
53
|
+
}
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
overflow-y: hidden;
|
|
55
|
+
.code-scroll-wrap {
|
|
56
|
+
width: 100%;
|
|
57
|
+
max-width: 100%;
|
|
58
|
+
min-width: 0;
|
|
59
|
+
overflow: auto;
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
.code-highlight-view {
|
|
62
|
+
width: max-content;
|
|
63
|
+
min-width: 100%;
|
|
64
|
+
box-sizing: border-box;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
57
67
|
}
|
|
58
68
|
}
|
|
59
69
|
}
|
|
60
|
-
|
|
61
70
|
}
|
package/src/App.tsx
CHANGED
|
@@ -4,12 +4,18 @@ import {CodeHighlight} from "@/components/code-highlight";
|
|
|
4
4
|
import {MapInputPanel} from "@/components/map-input-panel";
|
|
5
5
|
import {PanelCard} from "@/components/panel-card";
|
|
6
6
|
import {TraceChain} from "@/components/trace-chain";
|
|
7
|
+
import {applyNodeMethod, canIUse} from "@forge-kit/bridge-client";
|
|
8
|
+
import type {
|
|
9
|
+
MapInputConfig,
|
|
10
|
+
ResolveTraceMetaOutput,
|
|
11
|
+
ResolveTraceSnippetOutput,
|
|
12
|
+
} from "@/types";
|
|
7
13
|
import {
|
|
8
14
|
SourceMapUtils,
|
|
9
15
|
type ChainMapSlot,
|
|
10
16
|
type SourceMapChainState,
|
|
11
17
|
type TraceOutputState,
|
|
12
|
-
} from "@/utils/
|
|
18
|
+
} from "@/utils/trace-ui";
|
|
13
19
|
import '@forge-kit/component/style.css'
|
|
14
20
|
import './App.less'
|
|
15
21
|
|
|
@@ -17,20 +23,21 @@ interface AppProps {
|
|
|
17
23
|
themeProps?: React.ComponentProps<typeof Theme>
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
const DEFAULT_MAX_SNIPPET_PAYLOAD_BYTES = String(32 * 1024)
|
|
27
|
+
|
|
28
|
+
const stripMapExt = (fileName: string) => fileName.replace(/\.map$/i, "")
|
|
29
|
+
const getMapFileNameFromPath = (filePath: string) => {
|
|
30
|
+
const normalized = filePath.replace(/\\/g, "/")
|
|
31
|
+
const segments = normalized.split("/")
|
|
32
|
+
return segments[segments.length - 1] || filePath
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
const initialChainState: SourceMapChainState = {
|
|
27
|
-
sourceMaps: {},
|
|
28
|
-
sourceMapFileNames: [],
|
|
29
36
|
chainMapSlots: [],
|
|
30
37
|
entryFileName: "",
|
|
31
38
|
}
|
|
32
39
|
|
|
33
|
-
const initialInputState:
|
|
40
|
+
const initialInputState: MapInputConfig = {
|
|
34
41
|
entryLine: "",
|
|
35
42
|
entryColumn: "",
|
|
36
43
|
contextLineRadius: String(SourceMapUtils.DEFAULT_CONTEXT_LINE_RADIUS),
|
|
@@ -39,7 +46,7 @@ const initialInputState: InputState = {
|
|
|
39
46
|
export const App: React.FC<AppProps> = (props) => {
|
|
40
47
|
const {themeProps} = props
|
|
41
48
|
const [chainState, setChainState] = React.useState<SourceMapChainState>(initialChainState)
|
|
42
|
-
const [inputState, setInputState] = React.useState<
|
|
49
|
+
const [inputState, setInputState] = React.useState<MapInputConfig>(initialInputState)
|
|
43
50
|
const [outputState, setOutputState] = React.useState<TraceOutputState>(SourceMapUtils.createInitialOutputState())
|
|
44
51
|
|
|
45
52
|
const traceChainDisplayData = React.useMemo(() => {
|
|
@@ -47,16 +54,23 @@ export const App: React.FC<AppProps> = (props) => {
|
|
|
47
54
|
}, [outputState.traceData])
|
|
48
55
|
|
|
49
56
|
const applyChainSlots = (slots: ChainMapSlot[]) => {
|
|
50
|
-
setChainState(
|
|
57
|
+
setChainState({
|
|
58
|
+
chainMapSlots: slots,
|
|
59
|
+
entryFileName: slots.length ? stripMapExt(slots[0].mapFileName) : "",
|
|
60
|
+
})
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
const setOutputMessage = (message: string) => {
|
|
54
64
|
setOutputState((prev) => SourceMapUtils.patchOutputMessage(prev, message))
|
|
55
65
|
}
|
|
56
66
|
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
|
|
67
|
+
const handleAppendMapFilePath = (filePath: string) => {
|
|
68
|
+
const slot: ChainMapSlot = {
|
|
69
|
+
id: `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
70
|
+
mapFileName: getMapFileNameFromPath(filePath),
|
|
71
|
+
mapFilePath: filePath,
|
|
72
|
+
}
|
|
73
|
+
applyChainSlots([...chainState.chainMapSlots, slot])
|
|
60
74
|
}
|
|
61
75
|
|
|
62
76
|
const handleRemoveChainSlot = (slotId: string) => {
|
|
@@ -73,18 +87,50 @@ export const App: React.FC<AppProps> = (props) => {
|
|
|
73
87
|
entryLine: inputState.entryLine,
|
|
74
88
|
entryColumn: inputState.entryColumn,
|
|
75
89
|
contextLineRadius: inputState.contextLineRadius,
|
|
76
|
-
mapCount: chainState.
|
|
90
|
+
mapCount: chainState.chainMapSlots.length,
|
|
77
91
|
})
|
|
78
92
|
|
|
79
93
|
if (!validated.ok) return setOutputMessage(validated.message)
|
|
80
94
|
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
95
|
+
const mapFilePaths = chainState.chainMapSlots
|
|
96
|
+
.map((slot) => slot.mapFilePath)
|
|
97
|
+
.filter((path): path is string => Boolean(path))
|
|
98
|
+
|
|
99
|
+
if (!canIUse('applyNodeMethod')) return setOutputMessage("Node bridge 不可用,无法执行解析。")
|
|
100
|
+
|
|
101
|
+
if (mapFilePaths.length === 0) return setOutputMessage("未提供 map 文件路径,无法在 Node 侧解析。")
|
|
102
|
+
|
|
103
|
+
const payload = {
|
|
104
|
+
mapFilePaths,
|
|
105
|
+
entryFileName: validated.entry.fileName,
|
|
106
|
+
entryLine: String(validated.entry.lineNumber),
|
|
107
|
+
entryColumn: String(validated.entry.columnNumber),
|
|
108
|
+
contextLineRadius: String(validated.contextLineRadius),
|
|
109
|
+
maxSnippetPayloadBytes: DEFAULT_MAX_SNIPPET_PAYLOAD_BYTES,
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const nextOutput = await applyNodeMethod<ResolveTraceMetaOutput>('resolveTrace', JSON.stringify(payload))
|
|
114
|
+
setOutputState((prev) => ({
|
|
115
|
+
...prev,
|
|
116
|
+
traceData: nextOutput.traceData || [],
|
|
117
|
+
resolvedSourceMeta: nextOutput.resolvedSourceMeta || null,
|
|
118
|
+
traceCode: nextOutput.message || prev.traceCode,
|
|
119
|
+
traceHighlightLines: [],
|
|
120
|
+
}))
|
|
121
|
+
if (nextOutput?.resolvedSourceMeta) {
|
|
122
|
+
try {
|
|
123
|
+
const snippet = await applyNodeMethod<ResolveTraceSnippetOutput>('getSourceSnippet', JSON.stringify(payload))
|
|
124
|
+
setOutputState((prev) => ({...prev, ...snippet}))
|
|
125
|
+
} catch (error) {
|
|
126
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
127
|
+
setOutputState((prev) => SourceMapUtils.patchOutputMessage(prev, `源码片段加载失败: ${message}`))
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
132
|
+
setOutputMessage(`Node resolve failed: ${message}`)
|
|
133
|
+
}
|
|
88
134
|
}
|
|
89
135
|
|
|
90
136
|
return (
|
|
@@ -93,6 +139,7 @@ export const App: React.FC<AppProps> = (props) => {
|
|
|
93
139
|
<Flex className="forge-kit-plugin-source-map-prase-content" direction="column" gap="3">
|
|
94
140
|
<Flex className="top-cards" gap="3" align="stretch">
|
|
95
141
|
<TraceChain
|
|
142
|
+
className="top-trace-card"
|
|
96
143
|
slots={chainState.chainMapSlots.map((slot) => ({
|
|
97
144
|
id: slot.id,
|
|
98
145
|
mapFileName: slot.mapFileName,
|
|
@@ -101,16 +148,16 @@ export const App: React.FC<AppProps> = (props) => {
|
|
|
101
148
|
data={traceChainDisplayData}
|
|
102
149
|
onReorder={handleReorderChainSlots}
|
|
103
150
|
onDelete={handleRemoveChainSlot}
|
|
104
|
-
className="trace-chain-root"
|
|
105
151
|
/>
|
|
106
152
|
|
|
107
153
|
<MapInputPanel
|
|
154
|
+
className="top-input-card"
|
|
108
155
|
chainDepth={chainState.chainMapSlots.length}
|
|
109
156
|
entryFileName={chainState.entryFileName}
|
|
110
157
|
inputConfig={inputState}
|
|
111
158
|
onInputConfigChange={setInputState}
|
|
112
159
|
onResolve={handleResolveTrace}
|
|
113
|
-
|
|
160
|
+
onAppendMapFilePath={handleAppendMapFilePath}
|
|
114
161
|
/>
|
|
115
162
|
</Flex>
|
|
116
163
|
|
|
@@ -1,94 +1,87 @@
|
|
|
1
|
-
.
|
|
2
|
-
.input-panel-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
.input-panel-card {
|
|
2
|
+
.input-panel-content {
|
|
3
|
+
overflow: auto;
|
|
4
|
+
gap: 10px;
|
|
5
5
|
|
|
6
|
-
.input-
|
|
7
|
-
flex: 1;
|
|
8
|
-
overflow: auto;
|
|
9
|
-
gap: 10px;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.input-footer {
|
|
6
|
+
.input-summary-grid {
|
|
13
7
|
display: grid;
|
|
14
|
-
grid-template-
|
|
15
|
-
|
|
16
|
-
border-top: 1px solid var(--gray-5);
|
|
17
|
-
padding-top: 10px;
|
|
18
|
-
flex: 1;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
8
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
9
|
+
gap: 8px;
|
|
21
10
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
.input-summary-item {
|
|
12
|
+
border: 1px solid var(--gray-5);
|
|
13
|
+
border-radius: var(--radius-3);
|
|
14
|
+
padding: 8px 10px;
|
|
15
|
+
background: var(--gray-2);
|
|
27
16
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
17
|
+
.input-summary-label {
|
|
18
|
+
display: block;
|
|
19
|
+
color: var(--gray-10);
|
|
20
|
+
font-size: 12px;
|
|
21
|
+
margin-bottom: 4px;
|
|
22
|
+
}
|
|
34
23
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
.input-summary-value {
|
|
25
|
+
display: block;
|
|
26
|
+
color: var(--gray-12);
|
|
27
|
+
font-size: 13px;
|
|
28
|
+
font-weight: 600;
|
|
29
|
+
word-break: break-all;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
41
33
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
word-break: break-all;
|
|
48
|
-
}
|
|
34
|
+
.input-hints {
|
|
35
|
+
border: 1px dashed var(--gray-6);
|
|
36
|
+
border-radius: var(--radius-3);
|
|
37
|
+
padding: 8px 10px;
|
|
38
|
+
background: color-mix(in srgb, var(--gray-2) 70%, transparent);
|
|
49
39
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
40
|
+
.input-hints-title {
|
|
41
|
+
display: block;
|
|
42
|
+
font-size: 12px;
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
color: var(--gray-11);
|
|
45
|
+
margin-bottom: 6px;
|
|
46
|
+
}
|
|
56
47
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
48
|
+
.input-hints-item {
|
|
49
|
+
display: block;
|
|
50
|
+
font-size: 12px;
|
|
51
|
+
line-height: 1.6;
|
|
52
|
+
color: var(--gray-11);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
64
55
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
56
|
+
.input-footer {
|
|
57
|
+
display: grid;
|
|
58
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
59
|
+
row-gap: 10px;
|
|
60
|
+
border-top: 1px solid var(--gray-5);
|
|
61
|
+
padding-top: 10px;
|
|
71
62
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
63
|
+
.entry-row {
|
|
64
|
+
.field-row-compact {
|
|
65
|
+
flex: 1;
|
|
75
66
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
67
|
+
.field-label {
|
|
68
|
+
color: var(--gray-11);
|
|
69
|
+
font-size: 12px;
|
|
70
|
+
}
|
|
80
71
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
72
|
+
.rt-TextFieldRoot {
|
|
73
|
+
border-radius: 6px;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
84
77
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
font-size: 12px;
|
|
88
|
-
}
|
|
78
|
+
.entry-actions {
|
|
79
|
+
display: flex;
|
|
89
80
|
|
|
90
|
-
|
|
91
|
-
|
|
81
|
+
.entry-action-row {
|
|
82
|
+
width: auto;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
92
86
|
}
|
|
93
|
-
|
|
94
87
|
}
|
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import {Box, Button, Flex, Text, TextField} from "@forge-kit/component";
|
|
3
|
+
import {canIUse, openFileDialog} from "@forge-kit/bridge-client";
|
|
3
4
|
import {PanelCard} from "@/components/panel-card";
|
|
5
|
+
import type {MapInputConfig} from "@/types";
|
|
4
6
|
import {noop} from "@/utils";
|
|
7
|
+
import classNames from "classnames";
|
|
5
8
|
import "./index.less";
|
|
6
9
|
|
|
7
|
-
interface MapInputConfig {
|
|
8
|
-
entryLine: string
|
|
9
|
-
entryColumn: string
|
|
10
|
-
contextLineRadius: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
10
|
interface MapInputPanelProps {
|
|
11
|
+
className?: string
|
|
14
12
|
chainDepth: number
|
|
15
13
|
entryFileName: string
|
|
16
14
|
inputConfig: MapInputConfig
|
|
17
15
|
onInputConfigChange: (next: MapInputConfig) => void
|
|
18
16
|
onResolve: () => void
|
|
19
|
-
|
|
17
|
+
onAppendMapFilePath: (filePath: string) => void
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
interface MapInputFieldProps {
|
|
@@ -45,25 +43,26 @@ const MapInputField: React.FC<MapInputFieldProps> = (props) => {
|
|
|
45
43
|
|
|
46
44
|
export const MapInputPanel: React.FC<MapInputPanelProps> = (props) => {
|
|
47
45
|
const {
|
|
46
|
+
className,
|
|
48
47
|
chainDepth,
|
|
49
48
|
entryFileName,
|
|
50
49
|
inputConfig,
|
|
51
50
|
onInputConfigChange,
|
|
52
51
|
onResolve,
|
|
53
|
-
|
|
52
|
+
onAppendMapFilePath,
|
|
54
53
|
} = props
|
|
55
54
|
|
|
56
|
-
const openFilePicker = () => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
const openFilePicker = async () => {
|
|
56
|
+
if (!canIUse('openFileDialog')) return
|
|
57
|
+
|
|
58
|
+
const selected = await openFileDialog({
|
|
59
|
+
multiple: true,
|
|
60
|
+
filters: [{name: "Source Map", extensions: ["map", "json"]}],
|
|
61
|
+
})
|
|
62
|
+
const paths = Array.isArray(selected) ? selected : (selected ? [selected] : [])
|
|
63
|
+
paths.forEach((filePath) => {
|
|
64
|
+
if (typeof filePath === "string") onAppendMapFilePath(filePath)
|
|
65
|
+
})
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
const handleInputConfigChange = (field: keyof MapInputConfig, value: string) => {
|
|
@@ -71,7 +70,7 @@ export const MapInputPanel: React.FC<MapInputPanelProps> = (props) => {
|
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
return (
|
|
74
|
-
<PanelCard title="MAP INPUT" className="input-panel-card">
|
|
73
|
+
<PanelCard title="MAP INPUT" className={classNames("input-panel-card", className)}>
|
|
75
74
|
<Flex className="input-panel-content" direction='column' gap="3">
|
|
76
75
|
<Box className="input-summary-grid">
|
|
77
76
|
<Box className="input-summary-item">
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
+
.panel-card {
|
|
2
|
+
display: flex !important;
|
|
1
3
|
|
|
2
|
-
.panel-shell {
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
.panel-shell {
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
flex: 1;
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
.panel-title {
|
|
9
|
+
display: block;
|
|
10
|
+
padding: 0 0 var(--space-3);
|
|
11
|
+
margin-bottom: var(--space-3);
|
|
12
|
+
border-bottom: solid 1px var(--gray-5);
|
|
13
|
+
font-size: 12px;
|
|
14
|
+
letter-spacing: 0.1em;
|
|
15
|
+
color: var(--gray-11);
|
|
16
|
+
text-transform: uppercase;
|
|
17
|
+
}
|
|
15
18
|
}
|
|
16
|
-
}
|
|
17
19
|
|
|
20
|
+
}
|
|
18
21
|
|
|
@@ -5,7 +5,7 @@ import './index.less'
|
|
|
5
5
|
|
|
6
6
|
interface PanelCardProps {
|
|
7
7
|
title: string
|
|
8
|
-
className
|
|
8
|
+
className?: string
|
|
9
9
|
children?: React.ReactNode
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@ export const PanelCard: React.FC<PanelCardProps> = (props) => {
|
|
|
13
13
|
const {title, className, children} = props
|
|
14
14
|
|
|
15
15
|
return (
|
|
16
|
-
<Card className={classNames('panel-card', className)}>
|
|
16
|
+
<Card className={classNames('panel-card', className)} >
|
|
17
17
|
<Flex className="panel-shell" direction="column">
|
|
18
18
|
<Text className="panel-title">{title}</Text>
|
|
19
19
|
<>{children}</>
|