@teamvelix/velix 5.2.7 → 5.2.8

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,4 +1,4 @@
1
- import { definePlugin, PluginHooks, logger_default, loadPlugins, pluginManager, buildRouteTree, matchRoute, VERSION } from './chunk-SNWXKPXR.js';
1
+ import { definePlugin, PluginHooks, logger_default, loadPlugins, pluginManager, buildRouteTree, matchRoute, VERSION } from './chunk-RU23OKU5.js';
2
2
  import { loadConfig, resolvePaths } from './chunk-F24Q2MX3.js';
3
3
  import { getRegisteredIslands, generateAdvancedHydrationScript } from './chunk-JI2HJFUT.js';
4
4
  import { __dirname as __dirname$1, __require } from './chunk-BQ4HFLRL.js';
@@ -1191,99 +1191,84 @@ function generate404Page(pathname = "/") {
1191
1191
  <title>404 - Page Not Found | Velix v${VERSION}</title>
1192
1192
  <link rel="icon" href="/favicon.webp">
1193
1193
  <style>
1194
- * { margin: 0; padding: 0; box-sizing: border-box; }
1195
- body {
1196
- margin: 0;
1197
- background: #161616;
1198
- color: white;
1199
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1200
- display: flex;
1201
- align-items: center;
1202
- justify-content: center;
1203
- min-height: 100vh;
1204
- text-align: center;
1194
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
1195
+ body {
1196
+ background: #0a0a0a;
1197
+ color: #ededed;
1198
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
1199
+ display: flex;
1200
+ align-items: center;
1201
+ justify-content: center;
1202
+ min-height: 100vh;
1205
1203
  -webkit-font-smoothing: antialiased;
1206
1204
  }
1207
- .container {
1208
- max-width: 700px;
1209
- padding: 60px 40px;
1210
- position: relative;
1211
- z-index: 10;
1205
+ .container {
1206
+ display: flex;
1207
+ align-items: center;
1208
+ gap: 32px;
1209
+ padding: 32px;
1212
1210
  }
1213
- h1 {
1214
- font-size: 160px;
1215
- font-weight: 900;
1216
- margin: 0;
1217
- background: linear-gradient(135deg, #00e87a 0%, #22d3ee 100%);
1218
- -webkit-background-clip: text;
1219
- -webkit-text-fill-color: transparent;
1220
- line-height: 1;
1221
- letter-spacing: -0.05em;
1222
- animation: fadeIn 0.5s ease-out;
1211
+ .code {
1212
+ font-size: 48px;
1213
+ font-weight: 700;
1214
+ line-height: 1;
1215
+ color: #fff;
1216
+ border-right: 1px solid rgba(255,255,255,0.15);
1217
+ padding-right: 32px;
1223
1218
  }
1224
- h2 {
1225
- font-size: 32px;
1226
- font-weight: 700;
1227
- margin: 24px 0 12px;
1219
+ .body h1 {
1220
+ font-size: 18px;
1221
+ font-weight: 600;
1228
1222
  color: #ededed;
1229
- animation: fadeIn 0.5s ease-out 0.1s backwards;
1230
- }
1231
- p {
1232
- color: #888;
1233
- font-size: 16px;
1234
- line-height: 1.7;
1235
- margin-bottom: 36px;
1236
- animation: fadeIn 0.5s ease-out 0.2s backwards;
1223
+ margin-bottom: 8px;
1237
1224
  }
1238
- code {
1239
- background: #222;
1240
- padding: 3px 8px;
1241
- border-radius: 6px;
1242
- font-family: 'JetBrains Mono', monospace;
1243
- color: #00e87a;
1225
+ .body p {
1244
1226
  font-size: 14px;
1245
- border: 1px solid #333;
1227
+ color: #888;
1228
+ margin-bottom: 20px;
1246
1229
  }
1247
- .btn-group {
1248
- display: flex;
1249
- gap: 12px;
1250
- justify-content: center;
1251
- animation: fadeIn 0.5s ease-out 0.3s backwards;
1230
+ .body p code {
1231
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1232
+ font-size: 13px;
1233
+ background: rgba(255,255,255,0.07);
1234
+ padding: 2px 6px;
1235
+ border-radius: 4px;
1236
+ color: #ccc;
1252
1237
  }
1253
- .btn {
1254
- display: inline-block;
1255
- background: #222;
1256
- color: white;
1257
- text-decoration: none;
1258
- padding: 12px 28px;
1259
- border-radius: 10px;
1260
- font-weight: 600;
1238
+ .actions { display: flex; gap: 10px; }
1239
+ .btn {
1240
+ display: inline-block;
1241
+ padding: 8px 18px;
1242
+ border-radius: 8px;
1261
1243
  font-size: 14px;
1262
- transition: all 0.2s;
1263
- border: 1px solid #333;
1264
- cursor: pointer;
1244
+ font-weight: 500;
1245
+ text-decoration: none;
1246
+ transition: all .15s;
1247
+ border: 1px solid transparent;
1265
1248
  }
1266
- .btn:hover { background: #333; }
1267
- .btn-accent {
1268
- background: #00e87a;
1269
- color: #000;
1270
- border-color: #00e87a;
1249
+ .btn-primary {
1250
+ background: #fff;
1251
+ color: #000;
1271
1252
  }
1272
- .btn-accent:hover { background: #00d46e; }
1273
- @keyframes fadeIn {
1274
- from { opacity: 0; transform: translateY(16px); }
1275
- to { opacity: 1; transform: translateY(0); }
1253
+ .btn-primary:hover { background: #e5e5e5; }
1254
+ .btn-secondary {
1255
+ background: rgba(255,255,255,0.06);
1256
+ color: #ededed;
1257
+ border-color: rgba(255,255,255,0.1);
1276
1258
  }
1259
+ .btn-secondary:hover { background: rgba(255,255,255,0.1); }
1277
1260
  </style>
1278
1261
  </head>
1279
1262
  <body>
1280
1263
  <div class="container">
1281
- <h1>404</h1>
1282
- <h2>Page Not Found</h2>
1283
- <p>The page <code>${pathname}</code> could not be found.<br>It may have been moved or deleted.</p>
1284
- <div class="btn-group">
1285
- <a href="/" class="btn btn-accent">Return Home</a>
1286
- <a href="javascript:history.back()" class="btn">Go Back</a>
1264
+ <div class="code">404</div>
1265
+ <div class="body">
1266
+ <h1>This page could not be found</h1>
1267
+ <p>The path <code>${escapeHtml2(pathname)}</code> does not exist.</p>
1268
+ <div class="actions">
1269
+ <a href="/" class="btn btn-primary">Return Home</a>
1270
+ <a href="javascript:history.back()" class="btn btn-secondary">Go Back</a>
1271
+ </div>
1287
1272
  </div>
1288
1273
  </div>
1289
1274
  </body>
@@ -1296,35 +1281,33 @@ function generate500Page(options) {
1296
1281
  let errorLine = 0;
1297
1282
  let errorFile = "";
1298
1283
  if (isDev && stack) {
1299
- const stackLines = stack.split("\\n").filter((line) => line.trim());
1284
+ const stackLines = stack.split("\n").filter((l) => l.trim());
1300
1285
  frames = stackLines.slice(1).filter((line) => line.includes("at ")).map((frame) => {
1301
- const match = frame.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/) || frame.match(/at\s+(.+?):(\d+):(\d+)/);
1302
- if (match && match.length === 5) {
1303
- return { funcName: match[1].trim(), file: match[2], line: match[3], col: match[4] };
1304
- }
1305
- if (match && match.length === 4) {
1306
- return { funcName: "(anonymous)", file: match[1].trim(), line: match[2], col: match[3] };
1307
- }
1308
- const simpleMatch = frame.match(/at\s+(.+)/);
1309
- return { funcName: simpleMatch?.[1]?.trim() || "unknown", file: "", line: "", col: "" };
1286
+ const m1 = frame.match(/at\s+(.+?)\s+\((.+?):(\d+):\d+\)/);
1287
+ if (m1) return { call: m1[1].trim(), file: m1[2], line: parseInt(m1[3], 10) };
1288
+ const m2 = frame.match(/at\s+(.+?):(\d+):\d+/);
1289
+ if (m2) return { call: "(anonymous)", file: m2[1].trim(), line: parseInt(m2[2], 10) };
1290
+ return { call: frame.replace(/^\s*at\s+/, "").trim(), file: "", line: null };
1310
1291
  });
1311
- if (frames.length > 0) {
1312
- const firstFrame = frames.find((f) => f.file && !f.file.includes("node_modules")) || frames[0];
1313
- errorFile = firstFrame.file;
1314
- errorLine = parseInt(firstFrame.line, 10) || 0;
1292
+ const firstUserFrame = frames.find((f) => f.file && !f.file.includes("node_modules")) || frames[0];
1293
+ if (firstUserFrame) {
1294
+ errorFile = firstUserFrame.file;
1295
+ errorLine = firstUserFrame.line || 0;
1315
1296
  if (errorFile && errorLine > 0) {
1316
1297
  try {
1317
1298
  const fs4 = __require("fs");
1318
1299
  if (fs4.existsSync(errorFile)) {
1319
- const src = fs4.readFileSync(errorFile, "utf-8").split("\\n");
1320
- const start = Math.max(0, errorLine - 3);
1300
+ const src = fs4.readFileSync(errorFile, "utf-8").split("\n");
1301
+ const start = Math.max(0, errorLine - 4);
1321
1302
  const end = Math.min(src.length, errorLine + 3);
1322
1303
  sourceSnippet = src.slice(start, end).map((l, i) => {
1323
1304
  const num = start + i + 1;
1324
1305
  const isErr = num === errorLine;
1325
- const prefix = isErr ? "> " : " ";
1326
- const numStr = String(num).padStart(4, " ");
1327
- return `<div class="src-line${isErr ? " src-err" : ""}">${prefix}${numStr} | ${escapeHtml2(l)}</div>`;
1306
+ const numStr = String(num).padStart(3, " ");
1307
+ if (isErr) {
1308
+ return `<div class="src-line src-err"><span class="ln">${numStr}</span>${escapeHtml2(l)}</div>`;
1309
+ }
1310
+ return `<div class="src-line"><span class="ln">${numStr}</span>${escapeHtml2(l)}</div>`;
1328
1311
  }).join("");
1329
1312
  }
1330
1313
  } catch (_) {
@@ -1333,8 +1316,46 @@ function generate500Page(options) {
1333
1316
  }
1334
1317
  }
1335
1318
  const userFrames = frames.filter((f) => f.file && !f.file.includes("node_modules"));
1336
- const ignoredCount = frames.length - userFrames.length;
1319
+ const ignoredFrames = frames.filter((f) => !f.file || f.file.includes("node_modules"));
1337
1320
  const shortFile = errorFile.replace(/\\/g, "/").replace(/.*\/(?=app\/|server\/|src\/|pages\/)/, "");
1321
+ if (!isDev) {
1322
+ return `<!DOCTYPE html>
1323
+ <html lang="en">
1324
+ <head>
1325
+ <meta charset="UTF-8">
1326
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
1327
+ <title>500 - Internal Server Error | Velix</title>
1328
+ <link rel="icon" href="/favicon.webp">
1329
+ <style>
1330
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
1331
+ body {
1332
+ background: #0a0a0a;
1333
+ color: #ededed;
1334
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
1335
+ display: flex; align-items: center; justify-content: center;
1336
+ min-height: 100vh;
1337
+ -webkit-font-smoothing: antialiased;
1338
+ }
1339
+ .container { display: flex; align-items: center; gap: 32px; padding: 32px; }
1340
+ .code { font-size: 48px; font-weight: 700; color: #fff; border-right: 1px solid rgba(255,255,255,0.15); padding-right: 32px; }
1341
+ .body h1 { font-size: 18px; font-weight: 600; color: #ededed; margin-bottom: 8px; }
1342
+ .body p { font-size: 14px; color: #888; margin-bottom: 20px; }
1343
+ .btn { display: inline-block; padding: 8px 18px; border-radius: 8px; font-size: 14px; font-weight: 500; text-decoration: none; background: #fff; color: #000; transition: all .15s; }
1344
+ .btn:hover { background: #e5e5e5; }
1345
+ </style>
1346
+ </head>
1347
+ <body>
1348
+ <div class="container">
1349
+ <div class="code">500</div>
1350
+ <div class="body">
1351
+ <h1>Internal Server Error</h1>
1352
+ <p>A server-side exception has occurred. Please try again later.</p>
1353
+ <a href="/" class="btn">Return Home</a>
1354
+ </div>
1355
+ </div>
1356
+ </body>
1357
+ </html>`;
1358
+ }
1338
1359
  return `<!DOCTYPE html>
1339
1360
  <html lang="en">
1340
1361
  <head>
@@ -1343,291 +1364,328 @@ function generate500Page(options) {
1343
1364
  <title>Error | Velix v${VERSION}</title>
1344
1365
  <link rel="icon" href="/favicon.webp">
1345
1366
  <style>
1346
- :root {
1347
- --bg-body: #000;
1348
- --bg-card: #111;
1349
- --border: #333;
1350
- --text-main: #ededed;
1351
- --text-muted: #888;
1352
- --red-tag: #e5484d;
1353
- --red-bg: rgba(229, 72, 77, 0.15);
1354
- --code-bg: #000;
1355
- --code-hl: rgba(255,255,255,0.1);
1356
- --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
1357
- --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
1358
- }
1367
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
1359
1368
 
1360
- * { margin: 0; padding: 0; box-sizing: border-box; }
1361
1369
  body {
1362
- background: var(--bg-body);
1363
- color: var(--text-main);
1364
- font-family: var(--font-sans);
1370
+ background: rgba(0, 0, 0, 0.85);
1371
+ color: #ededed;
1372
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
1365
1373
  min-height: 100vh;
1366
- line-height: 1.7;
1367
- margin-bottom: 12px;
1368
- word-break: break-word;
1369
- }
1370
- .error-hint {
1371
- color: #22c55e;
1372
- font-size: 14px;
1373
- margin-bottom: 20px;
1374
+ display: flex;
1375
+ align-items: center;
1376
+ justify-content: center;
1377
+ padding: 24px;
1378
+ -webkit-font-smoothing: antialiased;
1374
1379
  }
1375
1380
 
1376
- /* Source block */
1377
- .source-block {
1378
- background: #1a1a1a;
1381
+ /* \u2500\u2500 Overlay Card \u2500\u2500 */
1382
+ .overlay {
1383
+ width: 100%;
1384
+ max-width: 940px;
1385
+ background: #111;
1379
1386
  border: 1px solid #2a2a2a;
1380
1387
  border-radius: 12px;
1388
+ box-shadow: 0 24px 64px rgba(0,0,0,0.6);
1381
1389
  overflow: hidden;
1382
- margin-bottom: 24px;
1390
+ display: flex;
1391
+ flex-direction: column;
1392
+ max-height: calc(100vh - 48px);
1383
1393
  }
1384
- .source-header {
1394
+
1395
+ /* \u2500\u2500 Header Bar \u2500\u2500 */
1396
+ .header {
1385
1397
  display: flex;
1386
1398
  align-items: center;
1387
1399
  justify-content: space-between;
1388
- padding: 10px 16px;
1389
- background: #1e1e1e;
1400
+ padding: 12px 20px;
1401
+ background: #161616;
1390
1402
  border-bottom: 1px solid #2a2a2a;
1403
+ gap: 12px;
1404
+ flex-shrink: 0;
1405
+ }
1406
+ .header-left {
1407
+ display: flex;
1408
+ align-items: center;
1409
+ gap: 8px;
1391
1410
  font-size: 13px;
1392
- color: #aaa;
1411
+ color: #888;
1393
1412
  }
1394
- .source-header .file-icon { color: #666; margin-right: 8px; }
1395
- .source-header a {
1413
+ .counter-badge {
1414
+ background: #1e1e1e;
1415
+ border: 1px solid #333;
1416
+ border-radius: 6px;
1417
+ padding: 2px 8px;
1418
+ font-size: 12px;
1419
+ color: #999;
1420
+ font-variant-numeric: tabular-nums;
1421
+ }
1422
+ .nav-btn {
1423
+ background: #1e1e1e;
1424
+ border: 1px solid #333;
1425
+ border-radius: 6px;
1426
+ color: #888;
1427
+ cursor: pointer;
1428
+ width: 24px;
1429
+ height: 24px;
1430
+ display: flex;
1431
+ align-items: center;
1432
+ justify-content: center;
1433
+ font-size: 13px;
1434
+ transition: all .15s;
1435
+ }
1436
+ .nav-btn:hover:not(:disabled) { background: #2a2a2a; color: #fff; }
1437
+ .nav-btn:disabled { opacity: 0.3; cursor: default; }
1438
+ .framework-tag {
1439
+ display: flex;
1440
+ align-items: center;
1441
+ gap: 6px;
1442
+ font-size: 12px;
1396
1443
  color: #666;
1397
- text-decoration: none;
1398
- transition: color .15s;
1399
1444
  }
1400
- .source-header a:hover { color: #fff; }
1445
+ .framework-tag::before {
1446
+ content: '';
1447
+ display: inline-block;
1448
+ width: 6px; height: 6px;
1449
+ border-radius: 50%;
1450
+ background: #3b82f6;
1451
+ }
1452
+
1453
+ /* \u2500\u2500 Scrollable Content \u2500\u2500 */
1454
+ .content {
1455
+ overflow-y: auto;
1456
+ flex: 1;
1457
+ }
1458
+
1459
+ /* \u2500\u2500 Error Summary \u2500\u2500 */
1460
+ .error-summary {
1461
+ padding: 28px 24px 20px;
1462
+ border-bottom: 1px solid #1e1e1e;
1463
+ }
1464
+ .error-label {
1465
+ display: inline-flex;
1466
+ align-items: center;
1467
+ gap: 6px;
1468
+ font-size: 11px;
1469
+ font-weight: 700;
1470
+ letter-spacing: 0.08em;
1471
+ text-transform: uppercase;
1472
+ color: #f87171;
1473
+ background: rgba(248, 113, 113, 0.1);
1474
+ border: 1px solid rgba(248, 113, 113, 0.25);
1475
+ padding: 3px 8px;
1476
+ border-radius: 4px;
1477
+ margin-bottom: 14px;
1478
+ }
1479
+ .error-label svg { width: 10px; height: 10px; fill: currentColor; }
1480
+ .error-message {
1481
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1482
+ font-size: 18px;
1483
+ font-weight: 600;
1484
+ line-height: 1.5;
1485
+ color: #fff;
1486
+ word-break: break-word;
1487
+ }
1488
+ .error-location {
1489
+ margin-top: 10px;
1490
+ font-size: 13px;
1491
+ color: #888;
1492
+ }
1493
+ .error-location strong { color: #ccc; }
1494
+
1495
+ /* \u2500\u2500 Source Block \u2500\u2500 */
1496
+ .source-block {
1497
+ border-bottom: 1px solid #1e1e1e;
1498
+ }
1499
+ .source-topbar {
1500
+ display: flex;
1501
+ align-items: center;
1502
+ padding: 10px 16px;
1503
+ background: #161616;
1504
+ border-bottom: 1px solid #1e1e1e;
1505
+ gap: 8px;
1506
+ font-size: 12px;
1507
+ color: #666;
1508
+ }
1509
+ .source-topbar .filepath { color: #aaa; font-family: ui-monospace, monospace; }
1401
1510
  .source-code {
1402
- padding: 12px 0;
1511
+ background: #0d0d0d;
1403
1512
  overflow-x: auto;
1404
- font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, monospace;
1513
+ padding: 10px 0;
1514
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1405
1515
  font-size: 13px;
1406
1516
  line-height: 1.7;
1407
1517
  }
1408
1518
  .src-line {
1409
- padding: 0 16px;
1519
+ display: flex;
1520
+ align-items: flex-start;
1521
+ padding: 0 20px;
1410
1522
  white-space: pre;
1411
- color: #888;
1523
+ color: #555;
1524
+ }
1525
+ .src-line .ln {
1526
+ color: #3a3a3a;
1527
+ text-align: right;
1528
+ width: 36px;
1529
+ margin-right: 16px;
1530
+ flex-shrink: 0;
1531
+ user-select: none;
1412
1532
  }
1413
1533
  .src-err {
1414
- background: rgba(255,50,50,0.1);
1415
- color: #ff8a8a;
1416
- font-weight: 500;
1534
+ background: rgba(239, 68, 68, 0.08);
1535
+ color: #fca5a5;
1536
+ position: relative;
1537
+ }
1538
+ .src-err .ln { color: #ef4444; }
1539
+ .src-err::before {
1540
+ content: '';
1541
+ position: absolute;
1542
+ left: 0;
1543
+ top: 0; bottom: 0;
1544
+ width: 3px;
1545
+ background: #ef4444;
1417
1546
  }
1418
1547
 
1419
- /* Call stack */
1420
- .stack-section { margin-bottom: 24px; }
1421
- .stack-header {
1422
- display: flex;
1423
- align-items: center;
1424
- justify-content: space-between;
1425
- margin-bottom: 12px;
1548
+ /* \u2500\u2500 Call Stack \u2500\u2500 */
1549
+ .callstack {
1550
+ padding: 20px 24px;
1426
1551
  }
1427
- .stack-label {
1428
- font-size: 15px;
1429
- font-weight: 700;
1430
- color: #ededed;
1552
+ .callstack-header {
1431
1553
  display: flex;
1432
1554
  align-items: center;
1433
- gap: 8px;
1555
+ justify-content: space-between;
1556
+ margin-bottom: 14px;
1434
1557
  }
1435
- .stack-count {
1436
- background: #2a2a2a;
1437
- color: #aaa;
1438
- padding: 2px 8px;
1439
- border-radius: 6px;
1440
- font-size: 12px;
1558
+ .callstack-title {
1559
+ font-size: 13px;
1441
1560
  font-weight: 600;
1561
+ color: #aaa;
1562
+ text-transform: uppercase;
1563
+ letter-spacing: 0.06em;
1442
1564
  }
1443
- .stack-toggle {
1444
- font-size: 13px;
1445
- color: #888;
1446
- cursor: pointer;
1565
+ .ignore-btn {
1566
+ font-size: 12px;
1567
+ color: #555;
1447
1568
  background: none;
1448
1569
  border: none;
1570
+ cursor: pointer;
1449
1571
  display: flex;
1450
1572
  align-items: center;
1451
1573
  gap: 4px;
1452
1574
  transition: color .15s;
1453
1575
  }
1454
- .stack-toggle:hover { color: #fff; }
1576
+ .ignore-btn:hover { color: #aaa; }
1577
+ .ignore-caret { transition: transform .2s; }
1578
+ .ignore-btn.open .ignore-caret { transform: rotate(90deg); }
1455
1579
 
1456
1580
  .frame {
1457
- padding: 12px 0;
1458
- border-bottom: 1px solid #1e1e1e;
1459
- }
1460
- .frame:last-child { border-bottom: none; }
1461
- .frame-name {
1462
- font-size: 14px;
1463
- font-weight: 600;
1464
- color: #ededed;
1465
- display: flex;
1466
- align-items: center;
1467
- gap: 6px;
1581
+ padding: 10px 12px;
1582
+ border-radius: 6px;
1468
1583
  margin-bottom: 4px;
1469
- }
1470
- .frame-name a {
1471
- color: #666;
1472
- text-decoration: none;
1473
- transition: color .15s;
1474
- }
1475
- .frame-name a:hover { color: #fff; }
1476
- .frame-loc {
1477
1584
  font-size: 13px;
1478
- color: #666;
1479
- font-family: 'JetBrains Mono', 'Fira Code', monospace;
1585
+ cursor: default;
1480
1586
  }
1481
-
1482
- /* Footer */
1483
- .footer-row {
1484
- display: flex;
1485
- justify-content: flex-end;
1486
- padding: 16px 0;
1487
- border-top: 1px solid #1e1e1e;
1488
- margin-top: 8px;
1587
+ .frame:hover { background: rgba(255,255,255,0.03); }
1588
+ .frame-call {
1589
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1590
+ font-weight: 600;
1591
+ color: #e2e8f0;
1592
+ margin-bottom: 3px;
1489
1593
  }
1490
- .footer-row a {
1491
- color: #ff6b6b;
1492
- text-decoration: none;
1493
- font-size: 13px;
1494
- font-weight: 500;
1495
- display: flex;
1496
- align-items: center;
1497
- gap: 6px;
1498
- transition: opacity .15s;
1594
+ .frame-loc {
1595
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1596
+ font-size: 12px;
1597
+ color: #555;
1499
1598
  }
1500
- .footer-row a:hover { opacity: 0.8; }
1599
+ .frame.ignored .frame-call { color: #444; }
1501
1600
 
1502
- /* Prod mode */
1503
- .prod-card {
1504
- background: #1a1a1a;
1505
- border: 1px solid #2a2a2a;
1506
- border-radius: 16px;
1507
- padding: 48px 32px;
1508
- text-align: center;
1509
- margin-top: 32px;
1510
- }
1511
- .prod-card h2 { font-size: 20px; margin-bottom: 8px; color: #fff; }
1512
- .prod-card p { font-size: 15px; color: #888; margin-bottom: 24px; }
1513
- .prod-card a {
1514
- display: inline-block;
1515
- padding: 10px 24px;
1516
- border-radius: 10px;
1517
- background: #222;
1518
- border: 1px solid #333;
1519
- color: #fff;
1520
- text-decoration: none;
1521
- font-weight: 500;
1522
- font-size: 14px;
1523
- transition: all .15s;
1524
- }
1525
- .prod-card a:hover { background: #333; }
1601
+ .ignored-section { margin-top: 8px; display: none; }
1602
+ .ignored-section.open { display: block; }
1526
1603
  </style>
1527
1604
  </head>
1528
1605
  <body>
1529
1606
  <div class="overlay">
1530
- <!-- Top Bar -->
1531
- <div class="top-bar">
1532
- <div class="page-nav">
1533
- <button id="prev-btn" onclick="changePage(-1)" disabled>\u2039</button>
1534
- <span><span id="current-page">1</span>/<span id="total-pages">1</span></span>
1535
- <button id="next-btn" onclick="changePage(1)" disabled>\u203A</button>
1536
- </div>
1537
- <div class="version-badge">
1538
- <span class="version-dot"></span>
1539
- Velix v${VERSION} esbuild
1540
- </div>
1607
+
1608
+ <!-- Header bar -->
1609
+ <div class="header">
1610
+ <div class="header-left">
1611
+ <button class="nav-btn" disabled>\u2039</button>
1612
+ <span class="counter-badge">1 / 1</span>
1613
+ <button class="nav-btn" disabled>\u203A</button>
1614
+ <span style="margin-left: 4px;">Unhandled Runtime Error</span>
1541
1615
  </div>
1616
+ <div class="framework-tag">Velix v${VERSION} \xB7 esbuild</div>
1617
+ </div>
1542
1618
 
1543
- <!-- Error Tag -->
1544
- <div class="error-tag">Unhandled Runtime Error</div>
1619
+ <!-- Scrollable content -->
1620
+ <div class="content">
1545
1621
 
1546
- <!-- Error Message -->
1547
- <div class="error-msg">${escapeHtml2(message)}</div>
1548
- ${pathname ? `<div class="error-hint">Check the render method of '<strong>${escapeHtml2(pathname)}</strong>'.</div>` : ""}
1622
+ <!-- Error summary -->
1623
+ <div class="error-summary">
1624
+ <div class="error-label">
1625
+ <svg viewBox="0 0 16 16"><path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm-.75 3.5a.75.75 0 0 1 1.5 0v4a.75.75 0 0 1-1.5 0v-4zm.75 6.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5z"/></svg>
1626
+ Runtime Error
1627
+ </div>
1628
+ <div class="error-message">${escapeHtml2(message)}</div>
1629
+ ${pathname ? `<div class="error-location">in <strong>${escapeHtml2(pathname)}</strong></div>` : ""}
1630
+ </div>
1549
1631
 
1550
- ${isDev && sourceSnippet ? `
1551
- <!-- Source Code Block -->
1632
+ ${sourceSnippet ? `
1633
+ <!-- Source code snippet -->
1552
1634
  <div class="source-block">
1553
- <div class="source-header">
1554
- <span><span class="file-icon">\u2699</span> ${escapeHtml2(shortFile)}${errorLine ? ` (${errorLine})` : ""}${userFrames[0]?.funcName ? ` @ ${escapeHtml2(userFrames[0].funcName)}` : ""}</span>
1555
- <a href="#" title="Open in editor">\u2197</a>
1556
- </div>
1557
- <div class="source-code">${sourceSnippet}</div>
1635
+ <div class="source-topbar">
1636
+ <svg width="12" height="12" fill="none" viewBox="0 0 24 24"><path stroke="#666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z"/><polyline stroke="#666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="14 2 14 8 20 8"/></svg>
1637
+ <span class="filepath">${escapeHtml2(shortFile)}${errorLine ? `:${errorLine}` : ""}</span>
1638
+ </div>
1639
+ <div class="source-code">${sourceSnippet}</div>
1558
1640
  </div>
1559
1641
  ` : ""}
1560
1642
 
1561
- ${isDev && frames.length > 0 ? `
1562
- <!-- Call Stack -->
1563
- <div class="stack-section">
1564
- <div class="stack-header">
1565
- <div class="stack-label">
1566
- Call Stack
1567
- <span class="stack-count">${frames.length}</span>
1568
- </div>
1569
- ${ignoredCount > 0 ? `<button class="stack-toggle" onclick="toggleIgnored()">Show ${ignoredCount} ignore-listed frames \u21D5</button>` : ""}
1570
- </div>
1571
- <div id="frames-list">
1572
- ${userFrames.map((f, i) => `
1573
- <div class="frame" data-frame="${i}">
1574
- <div class="frame-name">
1575
- <strong>${escapeHtml2(f.funcName)}</strong>
1576
- <a href="#" title="Open in editor">\u2197</a>
1577
- </div>
1578
- <div class="frame-loc">${escapeHtml2(f.file.replace(/.*[\\\/](?=app[\\\/]|server[\\\/]|src[\\\/]|pages[\\\/])/, ""))}${f.line ? ` (${f.line}:${f.col})` : ""}</div>
1579
- </div>
1580
- `).join("")}
1581
- </div>
1582
- <div id="ignored-frames" style="display:none;">
1583
- ${frames.filter((f) => !f.file || f.file.includes("node_modules")).map((f, i) => `
1584
- <div class="frame" data-frame="ignored-${i}">
1585
- <div class="frame-name" style="color:#666;">
1586
- <strong>${escapeHtml2(f.funcName)}</strong>
1587
- </div>
1588
- <div class="frame-loc">${escapeHtml2(f.file)}${f.line ? ` (${f.line}:${f.col})` : ""}</div>
1589
- </div>
1590
- `).join("")}
1643
+ <!-- Call stack -->
1644
+ <div class="callstack">
1645
+ <div class="callstack-header">
1646
+ <div class="callstack-title">Call Stack</div>
1647
+ ${ignoredFrames.length > 0 ? `
1648
+ <button class="ignore-btn" id="ignoreBtn" onclick="toggleIgnored()">
1649
+ <svg class="ignore-caret" width="12" height="12" viewBox="0 0 12 12" fill="none">
1650
+ <path d="M4.5 3L7.5 6L4.5 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
1651
+ </svg>
1652
+ ${ignoredFrames.length} ignored frames
1653
+ </button>
1654
+ ` : ""}
1655
+ </div>
1656
+
1657
+ <!-- User frames -->
1658
+ ${userFrames.map((f) => `
1659
+ <div class="frame">
1660
+ <div class="frame-call">${escapeHtml2(f.call)}</div>
1661
+ <div class="frame-loc">${escapeHtml2(f.file.replace(/\\/g, "/").replace(/.*\/(?=app\/|server\/|src\/|pages\/)/, ""))}${f.line ? `:${f.line}` : ""}</div>
1662
+ </div>
1663
+ `).join("")}
1664
+
1665
+ <!-- Ignored frames -->
1666
+ ${ignoredFrames.length > 0 ? `
1667
+ <div class="ignored-section" id="ignoredSection">
1668
+ ${ignoredFrames.map((f) => `
1669
+ <div class="frame ignored">
1670
+ <div class="frame-call">${escapeHtml2(f.call)}</div>
1671
+ <div class="frame-loc">${escapeHtml2(f.file)}${f.line ? `:${f.line}` : ""}</div>
1591
1672
  </div>
1673
+ `).join("")}
1674
+ </div>
1675
+ ` : ""}
1592
1676
  </div>
1593
- ` : `
1594
- <div class="prod-card">
1595
- <h2>Application Error</h2>
1596
- <p>A server-side error occurred. Check your server logs for more details.</p>
1597
- <a href="/">Return Home</a>
1598
- </div>
1599
- `}
1600
1677
 
1601
- <!-- Footer -->
1602
- <div class="footer-row">
1603
- <a href="javascript:location.reload()">Was this helpful? \u21BB</a>
1604
- </div>
1605
- </div>
1678
+ </div><!-- /content -->
1679
+ </div><!-- /overlay -->
1606
1680
 
1607
1681
  <script>
1608
- let currentPage = 1;
1609
- const totalPages = 1;
1610
- document.getElementById('total-pages').textContent = totalPages;
1611
-
1612
- function changePage(d) {
1613
- const next = currentPage + d;
1614
- if (next >= 1 && next <= totalPages) {
1615
- currentPage = next;
1616
- document.getElementById('current-page').textContent = currentPage;
1617
- document.getElementById('prev-btn').disabled = currentPage === 1;
1618
- document.getElementById('next-btn').disabled = currentPage === totalPages;
1619
- }
1620
- }
1621
-
1622
- function toggleIgnored() {
1623
- const el = document.getElementById('ignored-frames');
1624
- if (el) el.style.display = el.style.display === 'none' ? 'block' : 'none';
1625
- }
1626
-
1627
- document.addEventListener('keydown', (e) => {
1628
- if (e.key === 'ArrowLeft') changePage(-1);
1629
- if (e.key === 'ArrowRight') changePage(1);
1630
- });
1682
+ function toggleIgnored() {
1683
+ const btn = document.getElementById('ignoreBtn');
1684
+ const sec = document.getElementById('ignoredSection');
1685
+ if (!btn || !sec) return;
1686
+ const open = sec.classList.toggle('open');
1687
+ btn.classList.toggle('open', open);
1688
+ }
1631
1689
  </script>
1632
1690
  </body>
1633
1691
  </html>`;
@@ -2260,5 +2318,5 @@ function parseRawBody(req) {
2260
2318
  var server_default = { createServer, tailwindPlugin };
2261
2319
 
2262
2320
  export { RedirectError, bindArgs, callServerAction, composeMiddleware, cookies, createServer, deserializeArgs, executeAction, formAction, generateJsonLd, generateMetadataTags, generateRobotsTxt, generateSitemap, getAction, getMethod, getPathname, headers, html, isMethod, json, jsonLd, loadMiddleware, mergeMetadata, middlewares, notFound, parseFormData, parseJson, parseSearchParams, redirect, registerAction, runMiddleware, serverAction, server_default, tailwindPlugin, text, useActionContext, useVelixAction };
2263
- //# sourceMappingURL=chunk-MAAAP4QR.js.map
2264
- //# sourceMappingURL=chunk-MAAAP4QR.js.map
2321
+ //# sourceMappingURL=chunk-HMCBOHTD.js.map
2322
+ //# sourceMappingURL=chunk-HMCBOHTD.js.map