nyte 1.2.0 → 1.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.
- package/dist/client/DefaultNotFound.js +24 -31
- package/dist/client/ErrorModal.d.ts +2 -1
- package/dist/client/ErrorModal.js +39 -24
- package/dist/client/entry.client.js +88 -84
- package/package.json +1 -1
- package/src/client/DefaultNotFound.tsx +33 -40
- package/src/client/ErrorModal.tsx +42 -27
- package/src/client/entry.client.tsx +94 -88
|
@@ -9,68 +9,63 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
9
9
|
const react_1 = require("react");
|
|
10
10
|
const lucide_react_1 = require("lucide-react");
|
|
11
11
|
function ErrorPage() {
|
|
12
|
-
|
|
12
|
+
const [path, setPath] = (0, react_1.useState)('/');
|
|
13
|
+
// Estados apenas para mudar a COR do botão, sem mover nada de lugar
|
|
13
14
|
const [hoverHome, setHoverHome] = (0, react_1.useState)(false);
|
|
14
15
|
const [hoverRetry, setHoverRetry] = (0, react_1.useState)(false);
|
|
15
|
-
const [mounted, setMounted] = (0, react_1.useState)(false);
|
|
16
|
-
const [path, setPath] = (0, react_1.useState)('/');
|
|
17
16
|
(0, react_1.useEffect)(() => {
|
|
18
|
-
setMounted(true);
|
|
19
17
|
if (typeof window !== 'undefined') {
|
|
20
18
|
setPath(window.location.pathname);
|
|
21
19
|
}
|
|
22
20
|
}, []);
|
|
23
|
-
// --- GLOBAL STYLES
|
|
21
|
+
// --- GLOBAL STYLES ---
|
|
24
22
|
const globalStyles = `
|
|
25
23
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&family=JetBrains+Mono:wght@400;500&display=swap');
|
|
26
24
|
|
|
27
25
|
body {
|
|
28
26
|
margin: 0;
|
|
29
27
|
padding: 0;
|
|
30
|
-
/* SOLID DARK BACKGROUND HERE */
|
|
31
28
|
background-color: #0d0d0d;
|
|
32
29
|
color: #e2e8f0;
|
|
33
30
|
font-family: 'Inter', system-ui, sans-serif;
|
|
34
|
-
overflow: hidden;
|
|
31
|
+
overflow: hidden; /* Trava scroll */
|
|
35
32
|
height: 100vh;
|
|
36
33
|
width: 100vw;
|
|
37
|
-
position: relative;
|
|
38
34
|
}
|
|
39
35
|
|
|
40
36
|
* { box-sizing: border-box; }
|
|
41
37
|
`;
|
|
42
38
|
// --- INLINE STYLES ---
|
|
43
|
-
// Container updated for absolute perfect centering
|
|
44
39
|
const containerStyle = {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
// MUDANÇA CRÍTICA:
|
|
41
|
+
// Position fixed cobrindo a tela toda (inset: 0)
|
|
42
|
+
// Usamos Flexbox para centralizar. Isso não tem animação, é layout puro.
|
|
43
|
+
position: 'fixed',
|
|
44
|
+
top: 0,
|
|
45
|
+
left: 0,
|
|
46
|
+
right: 0,
|
|
47
|
+
bottom: 0,
|
|
48
|
+
zIndex: 9999,
|
|
49
49
|
display: 'flex',
|
|
50
50
|
flexDirection: 'column',
|
|
51
|
-
alignItems: 'center',
|
|
52
|
-
justifyContent: 'center',
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
alignItems: 'center', // Centraliza Horizontalmente
|
|
52
|
+
justifyContent: 'center', // Centraliza Verticalmente
|
|
53
|
+
width: '100vw',
|
|
54
|
+
height: '100vh',
|
|
55
|
+
background: '#0d0d0d', // Fundo sólido de segurança
|
|
56
56
|
};
|
|
57
57
|
const cardStyle = {
|
|
58
58
|
width: 'min(90%, 500px)',
|
|
59
59
|
display: 'flex',
|
|
60
60
|
flexDirection: 'column',
|
|
61
|
-
// Super Glassmorphism Dark (Matching Modal)
|
|
62
61
|
background: 'rgba(10, 10, 12, 0.95)',
|
|
63
|
-
// Cyan Glow Border + Deep Shadow
|
|
64
62
|
boxShadow: '0 0 0 1px rgba(34, 211, 238, 0.15), 0 40px 80px -20px rgba(0, 0, 0, 0.8)',
|
|
65
63
|
borderRadius: 20,
|
|
66
64
|
overflow: 'hidden',
|
|
67
65
|
position: 'relative',
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
transition: 'transform 0.5s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.5s ease',
|
|
71
|
-
pointerEvents: 'auto', // Re-enable clicks on the card itself
|
|
66
|
+
// REMOVIDO: transform, transition, opacity
|
|
67
|
+
// O card nasce desenhado na posição final.
|
|
72
68
|
};
|
|
73
|
-
// The Signature Neon Line
|
|
74
69
|
const neonLine = {
|
|
75
70
|
height: '1px',
|
|
76
71
|
width: '100%',
|
|
@@ -90,7 +85,6 @@ function ErrorPage() {
|
|
|
90
85
|
lineHeight: 1,
|
|
91
86
|
letterSpacing: '-0.04em',
|
|
92
87
|
color: '#fff',
|
|
93
|
-
// Subtle Gradient Text
|
|
94
88
|
background: 'linear-gradient(180deg, #ffffff 0%, #94a3b8 100%)',
|
|
95
89
|
WebkitBackgroundClip: 'text',
|
|
96
90
|
WebkitTextFillColor: 'transparent',
|
|
@@ -109,7 +103,6 @@ function ErrorPage() {
|
|
|
109
103
|
textAlign: 'left',
|
|
110
104
|
color: '#94a3b8',
|
|
111
105
|
};
|
|
112
|
-
// Button Generator (Reusable)
|
|
113
106
|
const getBtnStyle = (kind, hovering) => {
|
|
114
107
|
const base = {
|
|
115
108
|
display: 'flex',
|
|
@@ -120,7 +113,8 @@ function ErrorPage() {
|
|
|
120
113
|
fontSize: 13,
|
|
121
114
|
fontWeight: 600,
|
|
122
115
|
cursor: 'pointer',
|
|
123
|
-
|
|
116
|
+
// Mantive a transição de COR (0.2s), mas não move pixel nenhum
|
|
117
|
+
transition: 'background 0.2s ease, color 0.2s ease, box-shadow 0.2s ease',
|
|
124
118
|
border: 'none',
|
|
125
119
|
outline: 'none',
|
|
126
120
|
textDecoration: 'none',
|
|
@@ -148,12 +142,11 @@ function ErrorPage() {
|
|
|
148
142
|
alignItems: 'center',
|
|
149
143
|
gap: 10,
|
|
150
144
|
opacity: 0.4,
|
|
151
|
-
transition: 'opacity 0.3s',
|
|
145
|
+
transition: 'opacity 0.3s', // Apenas opacidade muda, sem movimento
|
|
152
146
|
textDecoration: 'none',
|
|
153
147
|
color: '#fff',
|
|
154
|
-
pointerEvents: 'auto', // Re-enable clicks on brand link
|
|
155
148
|
};
|
|
156
|
-
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: { __html: globalStyles } }), (0, jsx_runtime_1.jsxs)("div", { style: containerStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: cardStyle, children: [(0, jsx_runtime_1.jsx)("div", { style: neonLine }), (0, jsx_runtime_1.jsxs)("div", { style: contentStyle, children: [(0, jsx_runtime_1.jsx)("div", { style: codeStyle, children: "404" }), (0, jsx_runtime_1.jsxs)("div", { style: terminalBoxStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: 6, marginBottom: 8, opacity: 0.5 }, children: [(0, jsx_runtime_1.jsx)("div", { style: { width: 8, height: 8, borderRadius: '50%', background: '#f87171' } }), (0, jsx_runtime_1.jsx)("div", { style: { width: 8, height: 8, borderRadius: '50%', background: '#fbbf24' } }), (0, jsx_runtime_1.jsx)("div", { style: { width: 8, height: 8, borderRadius: '50%', background: '#4ade80' } })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { style: { color: '#c084fc' }, children: "GET" }), ' ', (0, jsx_runtime_1.jsx)("span", { style: { color: '#22d3ee' }, children: path })] }), (0, jsx_runtime_1.jsx)("div", { style: { marginTop: 4, color: '#f87171' }, children: (0, jsx_runtime_1.jsx)("span", { children: "Error: Route not found" }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: 12, width: '100%' }, children: [(0, jsx_runtime_1.jsxs)("a", { href: "/", style: { ...getBtnStyle('primary',
|
|
149
|
+
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: { __html: globalStyles } }), (0, jsx_runtime_1.jsxs)("div", { style: containerStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: cardStyle, children: [(0, jsx_runtime_1.jsx)("div", { style: neonLine }), (0, jsx_runtime_1.jsxs)("div", { style: contentStyle, children: [(0, jsx_runtime_1.jsx)("div", { style: codeStyle, children: "404" }), (0, jsx_runtime_1.jsxs)("div", { style: terminalBoxStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: 6, marginBottom: 8, opacity: 0.5 }, children: [(0, jsx_runtime_1.jsx)("div", { style: { width: 8, height: 8, borderRadius: '50%', background: '#f87171' } }), (0, jsx_runtime_1.jsx)("div", { style: { width: 8, height: 8, borderRadius: '50%', background: '#fbbf24' } }), (0, jsx_runtime_1.jsx)("div", { style: { width: 8, height: 8, borderRadius: '50%', background: '#4ade80' } })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { style: { color: '#c084fc' }, children: "GET" }), ' ', (0, jsx_runtime_1.jsx)("span", { style: { color: '#22d3ee' }, children: path })] }), (0, jsx_runtime_1.jsx)("div", { style: { marginTop: 4, color: '#f87171' }, children: (0, jsx_runtime_1.jsx)("span", { children: "Error: Route not found" }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: 12, width: '100%' }, children: [(0, jsx_runtime_1.jsxs)("a", { href: "/", onMouseEnter: () => setHoverHome(true), onMouseLeave: () => setHoverHome(false), style: { ...getBtnStyle('primary', hoverHome), flex: 1, justifyContent: 'center' }, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Home, { size: 16 }), "Back Home"] }), (0, jsx_runtime_1.jsxs)("button", { onClick: () => window.location.reload(), onMouseEnter: () => setHoverRetry(true), onMouseLeave: () => setHoverRetry(false), style: { ...getBtnStyle('secondary', hoverRetry), flex: 1, justifyContent: 'center' }, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.RefreshCw, { size: 16 }), "Retry"] })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
157
150
|
padding: '12px 32px',
|
|
158
151
|
background: 'rgba(0,0,0,0.3)',
|
|
159
152
|
borderTop: '1px solid rgba(255,255,255,0.03)',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
export interface NyteBuildError {
|
|
2
3
|
message?: string;
|
|
3
4
|
name?: string;
|
|
@@ -16,4 +17,4 @@ export declare function ErrorModal({ error, isOpen, onClose, onCopy, }: {
|
|
|
16
17
|
isOpen: boolean;
|
|
17
18
|
onClose: () => void;
|
|
18
19
|
onCopy?: () => void;
|
|
19
|
-
}):
|
|
20
|
+
}): React.ReactPortal | null;
|
|
@@ -19,17 +19,18 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
19
19
|
* limitations under the License.
|
|
20
20
|
*/
|
|
21
21
|
const react_1 = require("react");
|
|
22
|
+
const react_dom_1 = require("react-dom"); // <--- IMPORTANTE: Importar o Portal
|
|
22
23
|
// --- ANSI PARSER LOGIC ---
|
|
23
24
|
const ANSI_COLORS = {
|
|
24
|
-
'30': '#94a3b8',
|
|
25
|
-
'31': '#f87171',
|
|
26
|
-
'32': '#4ade80',
|
|
27
|
-
'33': '#facc15',
|
|
28
|
-
'34': '#60a5fa',
|
|
29
|
-
'35': '#c084fc',
|
|
30
|
-
'36': '#22d3ee',
|
|
31
|
-
'37': '#e2e8f0',
|
|
32
|
-
'90': '#64748b',
|
|
25
|
+
'30': '#94a3b8',
|
|
26
|
+
'31': '#f87171',
|
|
27
|
+
'32': '#4ade80',
|
|
28
|
+
'33': '#facc15',
|
|
29
|
+
'34': '#60a5fa',
|
|
30
|
+
'35': '#c084fc',
|
|
31
|
+
'36': '#22d3ee',
|
|
32
|
+
'37': '#e2e8f0',
|
|
33
|
+
'90': '#64748b',
|
|
33
34
|
};
|
|
34
35
|
function AnsiText({ text }) {
|
|
35
36
|
const parts = (0, react_1.useMemo)(() => {
|
|
@@ -45,7 +46,7 @@ function AnsiText({ text }) {
|
|
|
45
46
|
}
|
|
46
47
|
const code = match[1];
|
|
47
48
|
if (code === '39' || code === '0') {
|
|
48
|
-
currentColor = null;
|
|
49
|
+
currentColor = null;
|
|
49
50
|
}
|
|
50
51
|
else if (ANSI_COLORS[code]) {
|
|
51
52
|
currentColor = ANSI_COLORS[code];
|
|
@@ -65,13 +66,24 @@ function ErrorModal({ error, isOpen, onClose, onCopy, }) {
|
|
|
65
66
|
const [visible, setVisible] = (0, react_1.useState)(false);
|
|
66
67
|
const [isHoveringClose, setIsHoveringClose] = (0, react_1.useState)(false);
|
|
67
68
|
const [isHoveringCopy, setIsHoveringCopy] = (0, react_1.useState)(false);
|
|
69
|
+
// Estado para garantir que rodamos apenas no client-side (evita erro de SSR com document.body)
|
|
70
|
+
const [mounted, setMounted] = (0, react_1.useState)(false);
|
|
71
|
+
(0, react_1.useEffect)(() => {
|
|
72
|
+
setMounted(true);
|
|
73
|
+
return () => setMounted(false);
|
|
74
|
+
}, []);
|
|
68
75
|
(0, react_1.useEffect)(() => {
|
|
69
76
|
if (isOpen) {
|
|
77
|
+
// Trava o scroll do body quando o modal abre
|
|
78
|
+
document.body.style.overflow = 'hidden';
|
|
70
79
|
setTimeout(() => setVisible(true), 10);
|
|
71
80
|
}
|
|
72
81
|
else {
|
|
82
|
+
document.body.style.overflow = '';
|
|
73
83
|
setVisible(false);
|
|
74
84
|
}
|
|
85
|
+
// Limpeza de segurança
|
|
86
|
+
return () => { document.body.style.overflow = ''; };
|
|
75
87
|
}, [isOpen]);
|
|
76
88
|
(0, react_1.useEffect)(() => {
|
|
77
89
|
if (!isOpen)
|
|
@@ -83,26 +95,29 @@ function ErrorModal({ error, isOpen, onClose, onCopy, }) {
|
|
|
83
95
|
window.addEventListener('keydown', onKey);
|
|
84
96
|
return () => window.removeEventListener('keydown', onKey);
|
|
85
97
|
}, [isOpen, onClose]);
|
|
86
|
-
if (!isOpen || !error)
|
|
98
|
+
if (!mounted || !isOpen || !error)
|
|
87
99
|
return null;
|
|
88
|
-
// Combine raw error text to emulate a real terminal output
|
|
89
|
-
// Often build tools put the frame inside the message, so we prioritize message.
|
|
90
100
|
const rawOutput = error.message || '';
|
|
91
101
|
const stackOutput = error.stack ? `\n\nStack Trace:\n${error.stack}` : '';
|
|
92
102
|
// --- STYLES ---
|
|
93
103
|
const overlayStyle = {
|
|
94
104
|
position: 'fixed',
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
top: 0,
|
|
106
|
+
left: 0,
|
|
107
|
+
width: '100vw',
|
|
108
|
+
height: '100vh',
|
|
109
|
+
zIndex: 2147483647, // Max Z-Index seguro
|
|
110
|
+
// Fundo praticamente sólido (98% opacidade) para esconder o site atrás
|
|
111
|
+
background: visible ? 'rgba(5, 5, 5, 0.98)' : 'rgba(5, 5, 5, 0)',
|
|
112
|
+
backdropFilter: 'blur(10px)', // Blur extra caso algo vaze
|
|
113
|
+
WebkitBackdropFilter: 'blur(10px)',
|
|
100
114
|
display: 'flex',
|
|
101
115
|
alignItems: 'center',
|
|
102
116
|
justifyContent: 'center',
|
|
103
117
|
padding: 24,
|
|
104
118
|
transition: 'background 0.3s ease, opacity 0.3s ease',
|
|
105
119
|
opacity: visible ? 1 : 0,
|
|
120
|
+
boxSizing: 'border-box',
|
|
106
121
|
};
|
|
107
122
|
const cardStyle = {
|
|
108
123
|
width: '100%',
|
|
@@ -110,10 +125,8 @@ function ErrorModal({ error, isOpen, onClose, onCopy, }) {
|
|
|
110
125
|
maxHeight: '90vh',
|
|
111
126
|
display: 'flex',
|
|
112
127
|
flexDirection: 'column',
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
// Cyan Glow Border
|
|
116
|
-
boxShadow: '0 0 0 1px rgba(34, 211, 238, 0.15), 0 25px 50px -12px rgba(0, 0, 0, 0.9)',
|
|
128
|
+
background: 'rgba(10, 10, 12, 1)', // Card totalmente sólido
|
|
129
|
+
boxShadow: '0 0 0 1px rgba(34, 211, 238, 0.15), 0 50px 100px -20px rgba(0, 0, 0, 1)',
|
|
117
130
|
borderRadius: 16,
|
|
118
131
|
overflow: 'hidden',
|
|
119
132
|
transform: visible ? 'scale(1) translateY(0)' : 'scale(0.98) translateY(10px)',
|
|
@@ -175,10 +188,10 @@ function ErrorModal({ error, isOpen, onClose, onCopy, }) {
|
|
|
175
188
|
color: hovering ? '#fff' : 'rgba(255,255,255,0.5)',
|
|
176
189
|
};
|
|
177
190
|
};
|
|
178
|
-
|
|
191
|
+
const modalContent = ((0, jsx_runtime_1.jsx)("div", { style: overlayStyle, onMouseDown: onClose, children: (0, jsx_runtime_1.jsxs)("div", { style: cardStyle, onMouseDown: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsx)("div", { style: neonLine }), (0, jsx_runtime_1.jsxs)("div", { style: headerStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', gap: 12 }, children: [(0, jsx_runtime_1.jsx)("span", { style: {
|
|
179
192
|
fontSize: 12,
|
|
180
193
|
fontWeight: 800,
|
|
181
|
-
color: '#f87171',
|
|
194
|
+
color: '#f87171',
|
|
182
195
|
letterSpacing: '0.1em'
|
|
183
196
|
}, children: "ERROR" }), error.plugin && ((0, jsx_runtime_1.jsx)("span", { style: {
|
|
184
197
|
fontSize: 11,
|
|
@@ -196,4 +209,6 @@ function ErrorModal({ error, isOpen, onClose, onCopy, }) {
|
|
|
196
209
|
fontSize: 11,
|
|
197
210
|
color: 'rgba(255,255,255,0.2)'
|
|
198
211
|
}, children: [(0, jsx_runtime_1.jsx)("span", { children: "nyte-cli v2.0.0" }), (0, jsx_runtime_1.jsx)("span", { style: { color: '#22d3ee' }, children: "Watching for changes..." })] })] }) }));
|
|
212
|
+
// O PULO DO GATO: Renderiza direto no body para ignorar contexto de scroll dos pais
|
|
213
|
+
return (0, react_dom_1.createPortal)(modalContent, document.body);
|
|
199
214
|
}
|
|
@@ -269,91 +269,95 @@ function DevIndicator({ hasBuildError = false, onClickBuildError, }) {
|
|
|
269
269
|
const isReloading = hotState === 'reloading';
|
|
270
270
|
const isError = !!hasBuildError;
|
|
271
271
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("style", { children: `
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
font-size: 12px;
|
|
298
|
-
font-weight: 600;
|
|
299
|
-
letter-spacing: 0.05em;
|
|
272
|
+
@keyframes nyte-pulse {
|
|
273
|
+
0% { opacity: 0.4; }
|
|
274
|
+
50% { opacity: 1; }
|
|
275
|
+
100% { opacity: 0.4; }
|
|
276
|
+
}
|
|
277
|
+
@keyframes nyte-spin {
|
|
278
|
+
0% { transform: rotate(0deg); }
|
|
279
|
+
100% { transform: rotate(360deg); }
|
|
280
|
+
}
|
|
281
|
+
.nyte-dev-badge {
|
|
282
|
+
/* AQUI ESTÁ O QUE SEGURA ELE NA TELA: */
|
|
283
|
+
position: sticky;
|
|
284
|
+
bottom: 20px;
|
|
285
|
+
/* float e margens para forçar a direita no modo sticky */
|
|
286
|
+
float: right;
|
|
287
|
+
margin-right: 20px;
|
|
288
|
+
z-index: 999999;
|
|
289
|
+
|
|
290
|
+
display: flex;
|
|
291
|
+
align-items: center;
|
|
292
|
+
gap: 12px;
|
|
293
|
+
padding: 8px 14px;
|
|
294
|
+
background: rgba(15, 15, 20, 0.8);
|
|
295
|
+
backdrop-filter: blur(12px);
|
|
296
|
+
-webkit-backdrop-filter: blur(12px);
|
|
300
297
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
298
|
+
border-radius: 10px;
|
|
299
|
+
color: #fff;
|
|
300
|
+
font-family: 'Inter', ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
301
|
+
font-size: 12px;
|
|
302
|
+
font-weight: 600;
|
|
303
|
+
letter-spacing: 0.05em;
|
|
304
|
+
|
|
305
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
306
|
+
transition: all 0.2s ease;
|
|
307
|
+
cursor: default;
|
|
308
|
+
user-select: none;
|
|
309
|
+
}
|
|
310
|
+
.nyte-dev-badge.clickable {
|
|
311
|
+
cursor: pointer;
|
|
312
|
+
}
|
|
313
|
+
.nyte-dev-badge:hover {
|
|
314
|
+
border-color: rgba(142, 45, 226, 0.5);
|
|
315
|
+
transform: translateY(-2px);
|
|
316
|
+
}
|
|
317
|
+
.nyte-status-dot {
|
|
318
|
+
width: 8px;
|
|
319
|
+
height: 8px;
|
|
320
|
+
background: #10b981; /* Verde esmeralda */
|
|
321
|
+
border-radius: 50%;
|
|
322
|
+
box-shadow: 0 0 10px #10b981;
|
|
323
|
+
animation: nyte-pulse 2s infinite ease-in-out;
|
|
324
|
+
}
|
|
325
|
+
.nyte-status-dot.reloading {
|
|
326
|
+
background: #f59e0b; /* Amber */
|
|
327
|
+
box-shadow: 0 0 10px #f59e0b;
|
|
328
|
+
}
|
|
329
|
+
.nyte-status-dot.error {
|
|
330
|
+
background: #ef4444; /* Red */
|
|
331
|
+
box-shadow: 0 0 12px #ef4444;
|
|
332
|
+
animation: nyte-pulse 1.2s infinite ease-in-out;
|
|
333
|
+
}
|
|
334
|
+
.nyte-spinner {
|
|
335
|
+
width: 10px;
|
|
336
|
+
height: 10px;
|
|
337
|
+
border-radius: 50%;
|
|
338
|
+
border: 2px solid rgba(255,255,255,0.25);
|
|
339
|
+
border-top-color: rgba(255,255,255,0.85);
|
|
340
|
+
animation: nyte-spin 0.8s linear infinite;
|
|
341
|
+
}
|
|
342
|
+
.nyte-logo {
|
|
343
|
+
background: linear-gradient(135deg, #00a3a3, #808080);
|
|
344
|
+
-webkit-background-clip: text;
|
|
345
|
+
-webkit-text-fill-color: transparent;
|
|
346
|
+
font-weight: 800;
|
|
347
|
+
}
|
|
348
|
+
.nyte-error-pill {
|
|
349
|
+
margin-left: 6px;
|
|
350
|
+
padding: 2px 6px;
|
|
351
|
+
border-radius: 999px;
|
|
352
|
+
background: rgba(239, 68, 68, 0.18);
|
|
353
|
+
border: 1px solid rgba(239, 68, 68, 0.35);
|
|
354
|
+
color: rgba(255,255,255,0.9);
|
|
355
|
+
font-size: 10px;
|
|
356
|
+
font-weight: 800;
|
|
357
|
+
letter-spacing: 0.08em;
|
|
358
|
+
text-transform: uppercase;
|
|
359
|
+
}
|
|
360
|
+
` }), (0, jsx_runtime_1.jsxs)("div", { className: `nyte-dev-badge${isError ? ' clickable' : ''}`, title: isError ? 'Build com erro — clique para ver detalhes' : undefined, onClick: () => {
|
|
357
361
|
if (isError) {
|
|
358
362
|
onClickBuildError?.();
|
|
359
363
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nyte",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Nyte.js is a high-level framework for building web applications with ease and speed. It provides a robust set of tools and features to streamline development and enhance productivity.",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"author": "itsmuzin",
|
|
@@ -6,34 +6,31 @@ import React, { useState, useEffect } from 'react';
|
|
|
6
6
|
import { Home, RefreshCw, AlertTriangle } from 'lucide-react';
|
|
7
7
|
|
|
8
8
|
export default function ErrorPage() {
|
|
9
|
-
|
|
9
|
+
const [path, setPath] = useState('/');
|
|
10
|
+
|
|
11
|
+
// Estados apenas para mudar a COR do botão, sem mover nada de lugar
|
|
10
12
|
const [hoverHome, setHoverHome] = useState(false);
|
|
11
13
|
const [hoverRetry, setHoverRetry] = useState(false);
|
|
12
|
-
const [mounted, setMounted] = useState(false);
|
|
13
|
-
const [path, setPath] = useState('/');
|
|
14
14
|
|
|
15
15
|
useEffect(() => {
|
|
16
|
-
setMounted(true);
|
|
17
16
|
if (typeof window !== 'undefined') {
|
|
18
17
|
setPath(window.location.pathname);
|
|
19
18
|
}
|
|
20
19
|
}, []);
|
|
21
20
|
|
|
22
|
-
// --- GLOBAL STYLES
|
|
21
|
+
// --- GLOBAL STYLES ---
|
|
23
22
|
const globalStyles = `
|
|
24
23
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&family=JetBrains+Mono:wght@400;500&display=swap');
|
|
25
24
|
|
|
26
25
|
body {
|
|
27
26
|
margin: 0;
|
|
28
27
|
padding: 0;
|
|
29
|
-
/* SOLID DARK BACKGROUND HERE */
|
|
30
28
|
background-color: #0d0d0d;
|
|
31
29
|
color: #e2e8f0;
|
|
32
30
|
font-family: 'Inter', system-ui, sans-serif;
|
|
33
|
-
overflow: hidden;
|
|
31
|
+
overflow: hidden; /* Trava scroll */
|
|
34
32
|
height: 100vh;
|
|
35
33
|
width: 100vw;
|
|
36
|
-
position: relative;
|
|
37
34
|
}
|
|
38
35
|
|
|
39
36
|
* { box-sizing: border-box; }
|
|
@@ -41,39 +38,41 @@ export default function ErrorPage() {
|
|
|
41
38
|
|
|
42
39
|
// --- INLINE STYLES ---
|
|
43
40
|
|
|
44
|
-
// Container updated for absolute perfect centering
|
|
45
41
|
const containerStyle: React.CSSProperties = {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
// MUDANÇA CRÍTICA:
|
|
43
|
+
// Position fixed cobrindo a tela toda (inset: 0)
|
|
44
|
+
// Usamos Flexbox para centralizar. Isso não tem animação, é layout puro.
|
|
45
|
+
position: 'fixed',
|
|
46
|
+
top: 0,
|
|
47
|
+
left: 0,
|
|
48
|
+
right: 0,
|
|
49
|
+
bottom: 0,
|
|
50
|
+
zIndex: 9999,
|
|
51
|
+
|
|
50
52
|
display: 'flex',
|
|
51
53
|
flexDirection: 'column',
|
|
52
|
-
alignItems: 'center',
|
|
53
|
-
justifyContent: 'center',
|
|
54
|
-
|
|
55
|
-
width: '
|
|
56
|
-
|
|
54
|
+
alignItems: 'center', // Centraliza Horizontalmente
|
|
55
|
+
justifyContent: 'center', // Centraliza Verticalmente
|
|
56
|
+
|
|
57
|
+
width: '100vw',
|
|
58
|
+
height: '100vh',
|
|
59
|
+
background: '#0d0d0d', // Fundo sólido de segurança
|
|
57
60
|
};
|
|
58
61
|
|
|
59
62
|
const cardStyle: React.CSSProperties = {
|
|
60
63
|
width: 'min(90%, 500px)',
|
|
61
64
|
display: 'flex',
|
|
62
65
|
flexDirection: 'column',
|
|
63
|
-
// Super Glassmorphism Dark (Matching Modal)
|
|
64
66
|
background: 'rgba(10, 10, 12, 0.95)',
|
|
65
|
-
// Cyan Glow Border + Deep Shadow
|
|
66
67
|
boxShadow: '0 0 0 1px rgba(34, 211, 238, 0.15), 0 40px 80px -20px rgba(0, 0, 0, 0.8)',
|
|
67
68
|
borderRadius: 20,
|
|
68
69
|
overflow: 'hidden',
|
|
69
70
|
position: 'relative',
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
pointerEvents: 'auto', // Re-enable clicks on the card itself
|
|
71
|
+
|
|
72
|
+
// REMOVIDO: transform, transition, opacity
|
|
73
|
+
// O card nasce desenhado na posição final.
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
// The Signature Neon Line
|
|
77
76
|
const neonLine: React.CSSProperties = {
|
|
78
77
|
height: '1px',
|
|
79
78
|
width: '100%',
|
|
@@ -95,7 +94,6 @@ export default function ErrorPage() {
|
|
|
95
94
|
lineHeight: 1,
|
|
96
95
|
letterSpacing: '-0.04em',
|
|
97
96
|
color: '#fff',
|
|
98
|
-
// Subtle Gradient Text
|
|
99
97
|
background: 'linear-gradient(180deg, #ffffff 0%, #94a3b8 100%)',
|
|
100
98
|
WebkitBackgroundClip: 'text',
|
|
101
99
|
WebkitTextFillColor: 'transparent',
|
|
@@ -116,7 +114,6 @@ export default function ErrorPage() {
|
|
|
116
114
|
color: '#94a3b8',
|
|
117
115
|
};
|
|
118
116
|
|
|
119
|
-
// Button Generator (Reusable)
|
|
120
117
|
const getBtnStyle = (kind: 'primary' | 'secondary', hovering: boolean): React.CSSProperties => {
|
|
121
118
|
const base: React.CSSProperties = {
|
|
122
119
|
display: 'flex',
|
|
@@ -127,7 +124,8 @@ export default function ErrorPage() {
|
|
|
127
124
|
fontSize: 13,
|
|
128
125
|
fontWeight: 600,
|
|
129
126
|
cursor: 'pointer',
|
|
130
|
-
|
|
127
|
+
// Mantive a transição de COR (0.2s), mas não move pixel nenhum
|
|
128
|
+
transition: 'background 0.2s ease, color 0.2s ease, box-shadow 0.2s ease',
|
|
131
129
|
border: 'none',
|
|
132
130
|
outline: 'none',
|
|
133
131
|
textDecoration: 'none',
|
|
@@ -157,28 +155,22 @@ export default function ErrorPage() {
|
|
|
157
155
|
alignItems: 'center',
|
|
158
156
|
gap: 10,
|
|
159
157
|
opacity: 0.4,
|
|
160
|
-
transition: 'opacity 0.3s',
|
|
158
|
+
transition: 'opacity 0.3s', // Apenas opacidade muda, sem movimento
|
|
161
159
|
textDecoration: 'none',
|
|
162
160
|
color: '#fff',
|
|
163
|
-
pointerEvents: 'auto', // Re-enable clicks on brand link
|
|
164
161
|
};
|
|
165
162
|
|
|
166
163
|
return (
|
|
167
164
|
<div >
|
|
168
165
|
<style dangerouslySetInnerHTML={{ __html: globalStyles }} />
|
|
169
|
-
{/* Removed bgGlowStyle div for solid background */}
|
|
170
166
|
|
|
171
167
|
<div style={containerStyle}>
|
|
172
168
|
<div style={cardStyle}>
|
|
173
|
-
{/* Top Neon Line */}
|
|
174
169
|
<div style={neonLine} />
|
|
175
170
|
|
|
176
171
|
<div style={contentStyle}>
|
|
177
|
-
{/* 404 Title */}
|
|
178
172
|
<div style={codeStyle}>404</div>
|
|
179
173
|
|
|
180
|
-
|
|
181
|
-
{/* Tech/Terminal Detail */}
|
|
182
174
|
<div style={terminalBoxStyle}>
|
|
183
175
|
<div style={{ display: 'flex', gap: 6, marginBottom: 8, opacity: 0.5 }}>
|
|
184
176
|
<div style={{width: 8, height: 8, borderRadius: '50%', background: '#f87171'}}/>
|
|
@@ -194,18 +186,21 @@ export default function ErrorPage() {
|
|
|
194
186
|
</div>
|
|
195
187
|
</div>
|
|
196
188
|
|
|
197
|
-
{/* Actions */}
|
|
198
189
|
<div style={{ display: 'flex', gap: 12, width: '100%' }}>
|
|
199
190
|
<a
|
|
200
191
|
href="/"
|
|
201
|
-
|
|
192
|
+
onMouseEnter={() => setHoverHome(true)}
|
|
193
|
+
onMouseLeave={() => setHoverHome(false)}
|
|
194
|
+
style={{ ...getBtnStyle('primary', hoverHome), flex: 1, justifyContent: 'center' }}
|
|
202
195
|
>
|
|
203
196
|
<Home size={16} />
|
|
204
197
|
Back Home
|
|
205
198
|
</a>
|
|
206
199
|
<button
|
|
207
200
|
onClick={() => window.location.reload()}
|
|
208
|
-
|
|
201
|
+
onMouseEnter={() => setHoverRetry(true)}
|
|
202
|
+
onMouseLeave={() => setHoverRetry(false)}
|
|
203
|
+
style={{ ...getBtnStyle('secondary', hoverRetry), flex: 1, justifyContent: 'center' }}
|
|
209
204
|
>
|
|
210
205
|
<RefreshCw size={16} />
|
|
211
206
|
Retry
|
|
@@ -213,7 +208,6 @@ export default function ErrorPage() {
|
|
|
213
208
|
</div>
|
|
214
209
|
</div>
|
|
215
210
|
|
|
216
|
-
{/* Footer Status Bar (Matching Modal Footer) */}
|
|
217
211
|
<div style={{
|
|
218
212
|
padding: '12px 32px',
|
|
219
213
|
background: 'rgba(0,0,0,0.3)',
|
|
@@ -232,7 +226,6 @@ export default function ErrorPage() {
|
|
|
232
226
|
</div>
|
|
233
227
|
</div>
|
|
234
228
|
|
|
235
|
-
{/* Brand Footer */}
|
|
236
229
|
<a
|
|
237
230
|
href="https://npmjs.com/package/nyte"
|
|
238
231
|
target="_blank"
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import React, { useEffect, useState, useMemo } from 'react';
|
|
18
|
+
import { createPortal } from 'react-dom'; // <--- IMPORTANTE: Importar o Portal
|
|
18
19
|
|
|
19
20
|
export interface NyteBuildError {
|
|
20
21
|
message?: string;
|
|
@@ -32,15 +33,15 @@ export interface NyteBuildError {
|
|
|
32
33
|
|
|
33
34
|
// --- ANSI PARSER LOGIC ---
|
|
34
35
|
const ANSI_COLORS: Record<string, string> = {
|
|
35
|
-
'30': '#94a3b8',
|
|
36
|
-
'31': '#f87171',
|
|
37
|
-
'32': '#4ade80',
|
|
38
|
-
'33': '#facc15',
|
|
39
|
-
'34': '#60a5fa',
|
|
40
|
-
'35': '#c084fc',
|
|
41
|
-
'36': '#22d3ee',
|
|
42
|
-
'37': '#e2e8f0',
|
|
43
|
-
'90': '#64748b',
|
|
36
|
+
'30': '#94a3b8',
|
|
37
|
+
'31': '#f87171',
|
|
38
|
+
'32': '#4ade80',
|
|
39
|
+
'33': '#facc15',
|
|
40
|
+
'34': '#60a5fa',
|
|
41
|
+
'35': '#c084fc',
|
|
42
|
+
'36': '#22d3ee',
|
|
43
|
+
'37': '#e2e8f0',
|
|
44
|
+
'90': '#64748b',
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
function AnsiText({ text }: { text: string }) {
|
|
@@ -59,7 +60,7 @@ function AnsiText({ text }: { text: string }) {
|
|
|
59
60
|
|
|
60
61
|
const code = match[1];
|
|
61
62
|
if (code === '39' || code === '0') {
|
|
62
|
-
currentColor = null;
|
|
63
|
+
currentColor = null;
|
|
63
64
|
} else if (ANSI_COLORS[code]) {
|
|
64
65
|
currentColor = ANSI_COLORS[code];
|
|
65
66
|
}
|
|
@@ -102,13 +103,26 @@ export function ErrorModal({
|
|
|
102
103
|
const [visible, setVisible] = useState(false);
|
|
103
104
|
const [isHoveringClose, setIsHoveringClose] = useState(false);
|
|
104
105
|
const [isHoveringCopy, setIsHoveringCopy] = useState(false);
|
|
106
|
+
// Estado para garantir que rodamos apenas no client-side (evita erro de SSR com document.body)
|
|
107
|
+
const [mounted, setMounted] = useState(false);
|
|
108
|
+
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
setMounted(true);
|
|
111
|
+
return () => setMounted(false);
|
|
112
|
+
}, []);
|
|
105
113
|
|
|
106
114
|
useEffect(() => {
|
|
107
115
|
if (isOpen) {
|
|
116
|
+
// Trava o scroll do body quando o modal abre
|
|
117
|
+
document.body.style.overflow = 'hidden';
|
|
108
118
|
setTimeout(() => setVisible(true), 10);
|
|
109
119
|
} else {
|
|
120
|
+
document.body.style.overflow = '';
|
|
110
121
|
setVisible(false);
|
|
111
122
|
}
|
|
123
|
+
|
|
124
|
+
// Limpeza de segurança
|
|
125
|
+
return () => { document.body.style.overflow = ''; };
|
|
112
126
|
}, [isOpen]);
|
|
113
127
|
|
|
114
128
|
useEffect(() => {
|
|
@@ -120,10 +134,8 @@ export function ErrorModal({
|
|
|
120
134
|
return () => window.removeEventListener('keydown', onKey);
|
|
121
135
|
}, [isOpen, onClose]);
|
|
122
136
|
|
|
123
|
-
if (!isOpen || !error) return null;
|
|
137
|
+
if (!mounted || !isOpen || !error) return null;
|
|
124
138
|
|
|
125
|
-
// Combine raw error text to emulate a real terminal output
|
|
126
|
-
// Often build tools put the frame inside the message, so we prioritize message.
|
|
127
139
|
const rawOutput = error.message || '';
|
|
128
140
|
const stackOutput = error.stack ? `\n\nStack Trace:\n${error.stack}` : '';
|
|
129
141
|
|
|
@@ -131,17 +143,22 @@ export function ErrorModal({
|
|
|
131
143
|
|
|
132
144
|
const overlayStyle: React.CSSProperties = {
|
|
133
145
|
position: 'fixed',
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
146
|
+
top: 0,
|
|
147
|
+
left: 0,
|
|
148
|
+
width: '100vw',
|
|
149
|
+
height: '100vh',
|
|
150
|
+
zIndex: 2147483647, // Max Z-Index seguro
|
|
151
|
+
// Fundo praticamente sólido (98% opacidade) para esconder o site atrás
|
|
152
|
+
background: visible ? 'rgba(5, 5, 5, 0.98)' : 'rgba(5, 5, 5, 0)',
|
|
153
|
+
backdropFilter: 'blur(10px)', // Blur extra caso algo vaze
|
|
154
|
+
WebkitBackdropFilter: 'blur(10px)',
|
|
139
155
|
display: 'flex',
|
|
140
156
|
alignItems: 'center',
|
|
141
157
|
justifyContent: 'center',
|
|
142
158
|
padding: 24,
|
|
143
159
|
transition: 'background 0.3s ease, opacity 0.3s ease',
|
|
144
160
|
opacity: visible ? 1 : 0,
|
|
161
|
+
boxSizing: 'border-box',
|
|
145
162
|
};
|
|
146
163
|
|
|
147
164
|
const cardStyle: React.CSSProperties = {
|
|
@@ -150,10 +167,8 @@ export function ErrorModal({
|
|
|
150
167
|
maxHeight: '90vh',
|
|
151
168
|
display: 'flex',
|
|
152
169
|
flexDirection: 'column',
|
|
153
|
-
//
|
|
154
|
-
|
|
155
|
-
// Cyan Glow Border
|
|
156
|
-
boxShadow: '0 0 0 1px rgba(34, 211, 238, 0.15), 0 25px 50px -12px rgba(0, 0, 0, 0.9)',
|
|
170
|
+
background: 'rgba(10, 10, 12, 1)', // Card totalmente sólido
|
|
171
|
+
boxShadow: '0 0 0 1px rgba(34, 211, 238, 0.15), 0 50px 100px -20px rgba(0, 0, 0, 1)',
|
|
157
172
|
borderRadius: 16,
|
|
158
173
|
overflow: 'hidden',
|
|
159
174
|
transform: visible ? 'scale(1) translateY(0)' : 'scale(0.98) translateY(10px)',
|
|
@@ -221,7 +236,7 @@ export function ErrorModal({
|
|
|
221
236
|
};
|
|
222
237
|
};
|
|
223
238
|
|
|
224
|
-
|
|
239
|
+
const modalContent = (
|
|
225
240
|
<div style={overlayStyle} onMouseDown={onClose}>
|
|
226
241
|
<div style={cardStyle} onMouseDown={(e) => e.stopPropagation()}>
|
|
227
242
|
<div style={neonLine} />
|
|
@@ -232,7 +247,7 @@ export function ErrorModal({
|
|
|
232
247
|
<span style={{
|
|
233
248
|
fontSize: 12,
|
|
234
249
|
fontWeight: 800,
|
|
235
|
-
color: '#f87171',
|
|
250
|
+
color: '#f87171',
|
|
236
251
|
letterSpacing: '0.1em'
|
|
237
252
|
}}>
|
|
238
253
|
ERROR
|
|
@@ -275,10 +290,7 @@ export function ErrorModal({
|
|
|
275
290
|
|
|
276
291
|
{/* Terminal Output */}
|
|
277
292
|
<div style={terminalContent}>
|
|
278
|
-
{/* The star of the show: The ANSI parsed text */}
|
|
279
293
|
<AnsiText text={rawOutput} />
|
|
280
|
-
|
|
281
|
-
{/* Stack trace appended if exists and usually not in message */}
|
|
282
294
|
{stackOutput && (
|
|
283
295
|
<div style={{ marginTop: 24, opacity: 0.6, borderTop: '1px dashed rgba(255,255,255,0.1)', paddingTop: 16 }}>
|
|
284
296
|
<AnsiText text={stackOutput} />
|
|
@@ -302,4 +314,7 @@ export function ErrorModal({
|
|
|
302
314
|
</div>
|
|
303
315
|
</div>
|
|
304
316
|
);
|
|
317
|
+
|
|
318
|
+
// O PULO DO GATO: Renderiza direto no body para ignorar contexto de scroll dos pais
|
|
319
|
+
return createPortal(modalContent, document.body);
|
|
305
320
|
}
|
|
@@ -261,10 +261,12 @@ function App({ componentMap, routes, initialComponentPath, initialParams, layout
|
|
|
261
261
|
|
|
262
262
|
|
|
263
263
|
|
|
264
|
+
|
|
265
|
+
|
|
264
266
|
export function DevIndicator({
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}: {
|
|
267
|
+
hasBuildError = false,
|
|
268
|
+
onClickBuildError,
|
|
269
|
+
}: {
|
|
268
270
|
hasBuildError?: boolean;
|
|
269
271
|
onClickBuildError?: () => void;
|
|
270
272
|
}) {
|
|
@@ -303,91 +305,95 @@ export function DevIndicator({
|
|
|
303
305
|
<>
|
|
304
306
|
<style>
|
|
305
307
|
{`
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
308
|
+
@keyframes nyte-pulse {
|
|
309
|
+
0% { opacity: 0.4; }
|
|
310
|
+
50% { opacity: 1; }
|
|
311
|
+
100% { opacity: 0.4; }
|
|
312
|
+
}
|
|
313
|
+
@keyframes nyte-spin {
|
|
314
|
+
0% { transform: rotate(0deg); }
|
|
315
|
+
100% { transform: rotate(360deg); }
|
|
316
|
+
}
|
|
317
|
+
.nyte-dev-badge {
|
|
318
|
+
/* AQUI ESTÁ O QUE SEGURA ELE NA TELA: */
|
|
319
|
+
position: sticky;
|
|
320
|
+
bottom: 20px;
|
|
321
|
+
/* float e margens para forçar a direita no modo sticky */
|
|
322
|
+
float: right;
|
|
323
|
+
margin-right: 20px;
|
|
324
|
+
z-index: 999999;
|
|
325
|
+
|
|
326
|
+
display: flex;
|
|
327
|
+
align-items: center;
|
|
328
|
+
gap: 12px;
|
|
329
|
+
padding: 8px 14px;
|
|
330
|
+
background: rgba(15, 15, 20, 0.8);
|
|
331
|
+
backdrop-filter: blur(12px);
|
|
332
|
+
-webkit-backdrop-filter: blur(12px);
|
|
333
|
+
|
|
334
|
+
border-radius: 10px;
|
|
335
|
+
color: #fff;
|
|
336
|
+
font-family: 'Inter', ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
337
|
+
font-size: 12px;
|
|
338
|
+
font-weight: 600;
|
|
339
|
+
letter-spacing: 0.05em;
|
|
340
|
+
|
|
341
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
342
|
+
transition: all 0.2s ease;
|
|
343
|
+
cursor: default;
|
|
344
|
+
user-select: none;
|
|
345
|
+
}
|
|
346
|
+
.nyte-dev-badge.clickable {
|
|
347
|
+
cursor: pointer;
|
|
348
|
+
}
|
|
349
|
+
.nyte-dev-badge:hover {
|
|
350
|
+
border-color: rgba(142, 45, 226, 0.5);
|
|
351
|
+
transform: translateY(-2px);
|
|
352
|
+
}
|
|
353
|
+
.nyte-status-dot {
|
|
354
|
+
width: 8px;
|
|
355
|
+
height: 8px;
|
|
356
|
+
background: #10b981; /* Verde esmeralda */
|
|
357
|
+
border-radius: 50%;
|
|
358
|
+
box-shadow: 0 0 10px #10b981;
|
|
359
|
+
animation: nyte-pulse 2s infinite ease-in-out;
|
|
360
|
+
}
|
|
361
|
+
.nyte-status-dot.reloading {
|
|
362
|
+
background: #f59e0b; /* Amber */
|
|
363
|
+
box-shadow: 0 0 10px #f59e0b;
|
|
364
|
+
}
|
|
365
|
+
.nyte-status-dot.error {
|
|
366
|
+
background: #ef4444; /* Red */
|
|
367
|
+
box-shadow: 0 0 12px #ef4444;
|
|
368
|
+
animation: nyte-pulse 1.2s infinite ease-in-out;
|
|
369
|
+
}
|
|
370
|
+
.nyte-spinner {
|
|
371
|
+
width: 10px;
|
|
372
|
+
height: 10px;
|
|
373
|
+
border-radius: 50%;
|
|
374
|
+
border: 2px solid rgba(255,255,255,0.25);
|
|
375
|
+
border-top-color: rgba(255,255,255,0.85);
|
|
376
|
+
animation: nyte-spin 0.8s linear infinite;
|
|
377
|
+
}
|
|
378
|
+
.nyte-logo {
|
|
379
|
+
background: linear-gradient(135deg, #00a3a3, #808080);
|
|
380
|
+
-webkit-background-clip: text;
|
|
381
|
+
-webkit-text-fill-color: transparent;
|
|
382
|
+
font-weight: 800;
|
|
383
|
+
}
|
|
384
|
+
.nyte-error-pill {
|
|
385
|
+
margin-left: 6px;
|
|
386
|
+
padding: 2px 6px;
|
|
387
|
+
border-radius: 999px;
|
|
388
|
+
background: rgba(239, 68, 68, 0.18);
|
|
389
|
+
border: 1px solid rgba(239, 68, 68, 0.35);
|
|
390
|
+
color: rgba(255,255,255,0.9);
|
|
391
|
+
font-size: 10px;
|
|
392
|
+
font-weight: 800;
|
|
393
|
+
letter-spacing: 0.08em;
|
|
394
|
+
text-transform: uppercase;
|
|
395
|
+
}
|
|
396
|
+
`}
|
|
391
397
|
</style>
|
|
392
398
|
|
|
393
399
|
<div
|