@nine-lab/nine-mu 0.1.351 → 0.1.353
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/nine-mu.js +85 -74
- package/dist/nine-mu.js.map +1 -1
- package/dist/nine-mu.umd.js +1 -1
- package/dist/nine-mu.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/exception/ExceptionHook.js +78 -85
package/package.json
CHANGED
|
@@ -1,73 +1,68 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
// ==========================================
|
|
4
|
-
// 1. 터미널 프롬프트 테마 스타일 (
|
|
4
|
+
// 1. 터미널 프롬프트 테마 스타일 (줄간격 및 마진 정밀 교정)
|
|
5
5
|
// ==========================================
|
|
6
6
|
export const NineExceptionStyles = {
|
|
7
7
|
container: {
|
|
8
|
-
padding: '
|
|
8
|
+
padding: '25px',
|
|
9
9
|
margin: '20px',
|
|
10
10
|
background: '#121314', // 터미널 다크 블랙 배경
|
|
11
|
-
border: '1px solid #343A40', //
|
|
11
|
+
border: '1px solid #343A40', // 외곽 메탈릭 테두리
|
|
12
12
|
borderRadius: '6px',
|
|
13
|
-
fontFamily: 'Consolas, Monaco, "Courier New", monospace',
|
|
13
|
+
fontFamily: 'Consolas, Monaco, "Courier New", monospace',
|
|
14
14
|
textAlign: 'left',
|
|
15
|
-
boxShadow: '0 4px 12px rgba(0,0,0,0.3)'
|
|
15
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
|
|
16
|
+
lineHeight: '1.2' // ⭐ 줄간격을 터미널처럼 촘촘하게 제어
|
|
16
17
|
},
|
|
17
|
-
|
|
18
|
-
color: '#
|
|
19
|
-
marginTop: 0,
|
|
20
|
-
fontSize: '16px',
|
|
21
|
-
fontWeight: '600',
|
|
22
|
-
display: 'flex',
|
|
23
|
-
alignItems: 'center',
|
|
24
|
-
gap: '8px',
|
|
25
|
-
borderBottom: '1px solid #2D3139', // 상단 바 구분선 느낌
|
|
26
|
-
paddingBottom: '12px'
|
|
27
|
-
},
|
|
28
|
-
label: {
|
|
29
|
-
margin: '15px 0 8px 0',
|
|
18
|
+
systemError: {
|
|
19
|
+
color: '#E53E3E', // 터미널 레드 Warning
|
|
30
20
|
fontWeight: 'bold',
|
|
31
|
-
|
|
32
|
-
|
|
21
|
+
fontSize: '14px',
|
|
22
|
+
margin: '0 0 8px 0', // 하단 마진 축소
|
|
23
|
+
letterSpacing: '0.5px'
|
|
33
24
|
},
|
|
34
25
|
pre: {
|
|
35
|
-
background: '
|
|
36
|
-
color: '#F8F9FA',
|
|
37
|
-
padding: '
|
|
38
|
-
|
|
39
|
-
border: '
|
|
26
|
+
background: 'transparent',
|
|
27
|
+
color: '#F8F9FA',
|
|
28
|
+
padding: '0',
|
|
29
|
+
margin: '0 0 12px 0', // 하단 마진 축소하여 다음 라인과 밀착
|
|
30
|
+
border: 'none',
|
|
40
31
|
overflowX: 'auto',
|
|
41
32
|
whiteSpace: 'pre-wrap',
|
|
42
33
|
fontFamily: 'Consolas, Monaco, monospace',
|
|
43
|
-
fontSize: '
|
|
44
|
-
lineHeight: '1.5'
|
|
34
|
+
fontSize: '14px'
|
|
45
35
|
},
|
|
46
36
|
footer: {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
37
|
+
fontSize: '14px',
|
|
38
|
+
color: '#E2E8F0',
|
|
39
|
+
margin: '0', // 불필요한 공백 제거
|
|
50
40
|
display: 'flex',
|
|
51
41
|
flexDirection: 'column',
|
|
52
|
-
gap: '
|
|
42
|
+
gap: '6px'
|
|
53
43
|
},
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
promptRow: {
|
|
45
|
+
display: 'block', // 자연스러운 텍스트 흐름을 위해 block 처리
|
|
46
|
+
margin: '0'
|
|
47
|
+
},
|
|
48
|
+
// ⭐ y 글자에 직접 바인딩할 터미널 링크 스타일
|
|
49
|
+
cliLink: {
|
|
50
|
+
background: 'transparent',
|
|
51
|
+
color: '#38A169', // 터미널 그린
|
|
58
52
|
border: 'none',
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
padding: '0 2px',
|
|
54
|
+
fontFamily: 'Consolas, Monaco, monospace',
|
|
55
|
+
fontSize: '14px',
|
|
61
56
|
fontWeight: 'bold',
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
cursor: 'pointer',
|
|
58
|
+
textDecoration: 'underline',
|
|
59
|
+
textUnderlineOffset: '2px',
|
|
60
|
+
display: 'inline'
|
|
66
61
|
}
|
|
67
62
|
};
|
|
68
63
|
|
|
69
64
|
// ==========================================
|
|
70
|
-
// 2. 컴포넌트 본문
|
|
65
|
+
// 2. 컴포넌트 본문
|
|
71
66
|
// ==========================================
|
|
72
67
|
export class NineExceptionHook extends React.Component {
|
|
73
68
|
|
|
@@ -77,6 +72,7 @@ export class NineExceptionHook extends React.Component {
|
|
|
77
72
|
this.lastPath = window.location.pathname;
|
|
78
73
|
this.handleLocationChange = this.handleLocationChange.bind(this);
|
|
79
74
|
this.handleReport = this.handleReport.bind(this);
|
|
75
|
+
this.handleKeyDown = this.handleKeyDown.bind(this);
|
|
80
76
|
}
|
|
81
77
|
|
|
82
78
|
static getDerivedStateFromError(error) {
|
|
@@ -85,7 +81,6 @@ export class NineExceptionHook extends React.Component {
|
|
|
85
81
|
|
|
86
82
|
componentDidCatch(error, errorInfo) {
|
|
87
83
|
console.error("🚨 [Nine-Library] 본문 렌더링 에러 포착:", error);
|
|
88
|
-
|
|
89
84
|
if (this.props.onCatch) {
|
|
90
85
|
this.props.onCatch(error, errorInfo);
|
|
91
86
|
}
|
|
@@ -94,17 +89,28 @@ export class NineExceptionHook extends React.Component {
|
|
|
94
89
|
componentDidMount() {
|
|
95
90
|
window.addEventListener('popstate', this.handleLocationChange);
|
|
96
91
|
document.addEventListener('click', this.handleLocationChange, true);
|
|
92
|
+
window.addEventListener('keydown', this.handleKeyDown);
|
|
97
93
|
}
|
|
98
94
|
|
|
99
95
|
componentWillUnmount() {
|
|
100
96
|
window.removeEventListener('popstate', this.handleLocationChange);
|
|
101
97
|
document.removeEventListener('click', this.handleLocationChange, true);
|
|
98
|
+
window.removeEventListener('keydown', this.handleKeyDown);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
handleKeyDown(e) {
|
|
102
|
+
if (this.state.hasError && this.state.reportStatus === 'idle') {
|
|
103
|
+
if (e.key === 'y' || e.key === 'Y') {
|
|
104
|
+
e.preventDefault();
|
|
105
|
+
this.handleReport();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
102
108
|
}
|
|
103
109
|
|
|
104
110
|
handleLocationChange() {
|
|
105
111
|
setTimeout(() => {
|
|
106
112
|
if (this.state.hasError && this.lastPath !== window.location.pathname) {
|
|
107
|
-
console.log("[Nine-Library] 페이지 주소 변경 감지 ->
|
|
113
|
+
console.log("[Nine-Library] 페이지 주소 변경 감지 -> 에러 상태 초기화");
|
|
108
114
|
this.lastPath = window.location.pathname;
|
|
109
115
|
this.setState({ hasError: false, error: null, reportStatus: 'idle' });
|
|
110
116
|
}
|
|
@@ -124,7 +130,7 @@ export class NineExceptionHook extends React.Component {
|
|
|
124
130
|
console.warn("[Nine-Library] window.triggerAutoRecovery 가 정의되지 않았습니다.");
|
|
125
131
|
}
|
|
126
132
|
this.setState({ reportStatus: 'success' });
|
|
127
|
-
},
|
|
133
|
+
}, 600);
|
|
128
134
|
}
|
|
129
135
|
|
|
130
136
|
render() {
|
|
@@ -136,66 +142,53 @@ export class NineExceptionHook extends React.Component {
|
|
|
136
142
|
const errorMessage = this.state.error?.message || String(this.state.error);
|
|
137
143
|
const customStyles = this.props.styles || {};
|
|
138
144
|
|
|
139
|
-
let buttonText = '🚀 관제탑에 에러 피드백 전송하기';
|
|
140
|
-
if (this.state.reportStatus === 'sending') buttonText = '⏳ 관제탑 연락 중...';
|
|
141
|
-
if (this.state.reportStatus === 'success') buttonText = '✅ 전송 완료! AI 분석 시작';
|
|
142
|
-
|
|
143
145
|
return React.createElement(
|
|
144
146
|
'div',
|
|
145
147
|
{
|
|
146
148
|
style: { ...NineExceptionStyles.container, ...customStyles.container, ...this.props.containerStyle }
|
|
147
149
|
},
|
|
148
150
|
|
|
149
|
-
|
|
150
|
-
// 1. 상단 프롬프트 헤더 (시스템 상태 알림)
|
|
151
|
-
React.createElement(
|
|
152
|
-
'div',
|
|
153
|
-
{ style: { ...NineExceptionStyles.title, ...customStyles.title } },
|
|
154
|
-
React.createElement('span', { style: { color: '#38A169', marginRight: '5px' } }, 'nandoo@nine-mu:~$'),
|
|
155
|
-
'./system-check --status'
|
|
156
|
-
), */
|
|
157
|
-
|
|
158
|
-
// 2. 시스템 에러 감지 출력 로그
|
|
151
|
+
// 1. 에러 감지 로그
|
|
159
152
|
React.createElement(
|
|
160
153
|
'div',
|
|
161
|
-
{ style: {
|
|
154
|
+
{ style: { ...NineExceptionStyles.systemError, ...customStyles.systemError } },
|
|
162
155
|
'[SYSTEM] COMPONENT RENDER ERROR DETECTED'
|
|
163
156
|
),
|
|
164
157
|
|
|
165
|
-
|
|
166
|
-
// 3. 명령어 입력 시뮬레이션 ($ cat error.log)
|
|
167
|
-
React.createElement(
|
|
168
|
-
'p',
|
|
169
|
-
{ style: { ...NineExceptionStyles.label, ...customStyles.label } },
|
|
170
|
-
React.createElement('span', { style: { color: '#3182CE', marginRight: '6px' } }, 'nandoo@nine-mu:~$'),
|
|
171
|
-
'cat error.log'
|
|
172
|
-
), */
|
|
173
|
-
|
|
174
|
-
// 4. 에러 내용 본문 박스
|
|
158
|
+
// 2. 에러 내용 (하단 마진을 줄여 다음 줄과 간격을 맞춤)
|
|
175
159
|
React.createElement('pre', { style: { ...NineExceptionStyles.pre, ...customStyles.pre } }, errorMessage),
|
|
176
160
|
|
|
177
|
-
//
|
|
161
|
+
// 3. CLI 프롬프트 및 링크 영역
|
|
178
162
|
React.createElement(
|
|
179
163
|
'div',
|
|
180
164
|
{ style: { ...NineExceptionStyles.footer, ...customStyles.footer } },
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
165
|
+
|
|
166
|
+
this.state.reportStatus === 'idle' && React.createElement(
|
|
167
|
+
'div',
|
|
168
|
+
{ style: NineExceptionStyles.promptRow },
|
|
169
|
+
React.createElement('span', null, 'Send error log to Control Tower ('),
|
|
170
|
+
React.createElement(
|
|
171
|
+
'button',
|
|
172
|
+
{
|
|
173
|
+
style: { ...NineExceptionStyles.cliLink, ...customStyles.cliLink },
|
|
174
|
+
onClick: this.handleReport
|
|
189
175
|
},
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
176
|
+
'y'
|
|
177
|
+
),
|
|
178
|
+
React.createElement('span', null, '/n)?')
|
|
179
|
+
),
|
|
180
|
+
|
|
181
|
+
this.state.reportStatus === 'sending' && React.createElement(
|
|
182
|
+
'div',
|
|
183
|
+
{ style: { color: '#ED8936' } },
|
|
184
|
+
'>> Connecting to Control Tower... Sending payload.'
|
|
194
185
|
),
|
|
186
|
+
|
|
195
187
|
this.state.reportStatus === 'success' && React.createElement(
|
|
196
188
|
'div',
|
|
197
|
-
{ style: {
|
|
198
|
-
'
|
|
189
|
+
{ style: { display: 'flex', flexDirection: 'column', gap: '4px' } },
|
|
190
|
+
React.createElement('div', { style: { color: '#38A169', fontWeight: 'bold' } }, '>> Transmit complete. Core engine initialized.'),
|
|
191
|
+
React.createElement('div', { style: { color: '#A0AEC0', fontStyle: 'italic', fontSize: '13px' } }, 'AI가 소스 코드를 재수정하는 동안 잠시만 기다려주세요...')
|
|
199
192
|
)
|
|
200
193
|
)
|
|
201
194
|
);
|