@jxrstudios/jxr 1.0.10 → 1.1.11
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/bin/jxr.js +6 -0
- package/dist/index.js +57 -2
- package/dist/jxr-server-manager.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/jxr-server-manager.ts +65 -2
- package/zzz_react_template/App.tsx +43 -156
- package/zzz_react_template/components/ErrorBoundary.tsx +62 -0
- package/zzz_react_template/components/ManusDialog.tsx +85 -0
- package/zzz_react_template/components/Map.tsx +155 -0
- package/zzz_react_template/components/jxr/CodeEditor.tsx +313 -0
- package/zzz_react_template/components/jxr/FileExplorer.tsx +230 -0
- package/zzz_react_template/components/jxr/IDEShell.tsx +159 -0
- package/zzz_react_template/components/jxr/LandingPage.tsx +414 -0
- package/zzz_react_template/components/jxr/LivePreview.tsx +169 -0
- package/zzz_react_template/components/jxr/PerformanceDashboard.tsx +379 -0
- package/zzz_react_template/components/jxr/TopBar.tsx +149 -0
- package/zzz_react_template/components/ui/accordion.tsx +64 -0
- package/zzz_react_template/components/ui/alert-dialog.tsx +155 -0
- package/zzz_react_template/components/ui/alert.tsx +66 -0
- package/zzz_react_template/components/ui/aspect-ratio.tsx +9 -0
- package/zzz_react_template/components/ui/avatar.tsx +51 -0
- package/zzz_react_template/components/ui/badge.tsx +46 -0
- package/zzz_react_template/components/ui/breadcrumb.tsx +109 -0
- package/zzz_react_template/components/ui/button-group.tsx +83 -0
- package/zzz_react_template/components/ui/button.tsx +60 -0
- package/zzz_react_template/components/ui/calendar.tsx +211 -0
- package/zzz_react_template/components/ui/card.tsx +92 -0
- package/zzz_react_template/components/ui/carousel.tsx +239 -0
- package/zzz_react_template/components/ui/chart.tsx +355 -0
- package/zzz_react_template/components/ui/checkbox.tsx +30 -0
- package/zzz_react_template/components/ui/collapsible.tsx +31 -0
- package/zzz_react_template/components/ui/command.tsx +184 -0
- package/zzz_react_template/components/ui/context-menu.tsx +250 -0
- package/zzz_react_template/components/ui/dialog.tsx +209 -0
- package/zzz_react_template/components/ui/drawer.tsx +133 -0
- package/zzz_react_template/components/ui/dropdown-menu.tsx +255 -0
- package/zzz_react_template/components/ui/empty.tsx +104 -0
- package/zzz_react_template/components/ui/field.tsx +242 -0
- package/zzz_react_template/components/ui/form.tsx +168 -0
- package/zzz_react_template/components/ui/hover-card.tsx +42 -0
- package/zzz_react_template/components/ui/input-group.tsx +168 -0
- package/zzz_react_template/components/ui/input-otp.tsx +75 -0
- package/zzz_react_template/components/ui/input.tsx +70 -0
- package/zzz_react_template/components/ui/item.tsx +193 -0
- package/zzz_react_template/components/ui/kbd.tsx +28 -0
- package/zzz_react_template/components/ui/label.tsx +22 -0
- package/zzz_react_template/components/ui/menubar.tsx +274 -0
- package/zzz_react_template/components/ui/navigation-menu.tsx +168 -0
- package/zzz_react_template/components/ui/pagination.tsx +127 -0
- package/zzz_react_template/components/ui/popover.tsx +46 -0
- package/zzz_react_template/components/ui/progress.tsx +29 -0
- package/zzz_react_template/components/ui/radio-group.tsx +43 -0
- package/zzz_react_template/components/ui/resizable.tsx +54 -0
- package/zzz_react_template/components/ui/scroll-area.tsx +56 -0
- package/zzz_react_template/components/ui/select.tsx +185 -0
- package/zzz_react_template/components/ui/separator.tsx +26 -0
- package/zzz_react_template/components/ui/sheet.tsx +139 -0
- package/zzz_react_template/components/ui/sidebar.tsx +734 -0
- package/zzz_react_template/components/ui/skeleton.tsx +13 -0
- package/zzz_react_template/components/ui/slider.tsx +61 -0
- package/zzz_react_template/components/ui/sonner.tsx +23 -0
- package/zzz_react_template/components/ui/spinner.tsx +16 -0
- package/zzz_react_template/components/ui/switch.tsx +29 -0
- package/zzz_react_template/components/ui/table.tsx +114 -0
- package/zzz_react_template/components/ui/tabs.tsx +64 -0
- package/zzz_react_template/components/ui/textarea.tsx +67 -0
- package/zzz_react_template/components/ui/toggle-group.tsx +73 -0
- package/zzz_react_template/components/ui/toggle.tsx +45 -0
- package/zzz_react_template/components/ui/tooltip.tsx +59 -0
- package/zzz_react_template/const.ts +17 -0
- package/zzz_react_template/contexts/JXRContext.tsx +264 -0
- package/zzz_react_template/contexts/ThemeContext.tsx +64 -0
- package/zzz_react_template/hooks/useComposition.ts +81 -0
- package/zzz_react_template/hooks/useMobile.tsx +21 -0
- package/zzz_react_template/hooks/usePersistFn.ts +20 -0
- package/zzz_react_template/index.css +518 -11
- package/zzz_react_template/lib/jxr-runtime/index.ts +201 -0
- package/zzz_react_template/lib/jxr-runtime/module-resolver.ts +520 -0
- package/zzz_react_template/lib/jxr-runtime/moq-transport.ts +267 -0
- package/zzz_react_template/lib/jxr-runtime/web-crypto.ts +279 -0
- package/zzz_react_template/lib/jxr-runtime/worker-pool.ts +321 -0
- package/zzz_react_template/lib/utils.ts +6 -0
- package/zzz_react_template/main.tsx +4 -9
- package/zzz_react_template/pages/Docs.tsx +955 -0
- package/zzz_react_template/pages/Home.tsx +1080 -0
- package/zzz_react_template/pages/NotFound.tsx +105 -0
- package/zzz_react_template/tsconfig.json +24 -0
package/bin/jxr.js
CHANGED
|
@@ -55,6 +55,12 @@ if (command === "init") {
|
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// Copy tsconfig.json
|
|
59
|
+
await cp(
|
|
60
|
+
path.join(templateDir, "tsconfig.json"),
|
|
61
|
+
path.join(projectDir, "tsconfig.json")
|
|
62
|
+
);
|
|
63
|
+
|
|
58
64
|
console.log(`✅ Project created: ${projectDir}`);
|
|
59
65
|
console.log("");
|
|
60
66
|
console.log("Next steps:");
|
package/dist/index.js
CHANGED
|
@@ -1815,7 +1815,55 @@ var JXRServerManager = class {
|
|
|
1815
1815
|
return;
|
|
1816
1816
|
}
|
|
1817
1817
|
if (vfsPath.endsWith(".css")) {
|
|
1818
|
-
|
|
1818
|
+
let cssContent = file.content;
|
|
1819
|
+
if (vfsPath === "/src/index.css") {
|
|
1820
|
+
try {
|
|
1821
|
+
const fs = await import("fs");
|
|
1822
|
+
const compiledPath = path.join(process.cwd(), "src", "index.compiled.css");
|
|
1823
|
+
if (fs.existsSync(compiledPath)) {
|
|
1824
|
+
cssContent = fs.readFileSync(compiledPath, "utf-8");
|
|
1825
|
+
console.log(`[JXR] Using pre-compiled Tailwind CSS from index.compiled.css`);
|
|
1826
|
+
} else {
|
|
1827
|
+
const { execSync } = await import("child_process");
|
|
1828
|
+
const os = await import("os");
|
|
1829
|
+
const tmpDir = os.tmpdir();
|
|
1830
|
+
const inputFile = path.join(tmpDir, `jxr-tailwind-${Date.now()}.css`);
|
|
1831
|
+
const outputFile = path.join(tmpDir, `jxr-tailwind-${Date.now()}.compiled.css`);
|
|
1832
|
+
fs.writeFileSync(inputFile, cssContent);
|
|
1833
|
+
try {
|
|
1834
|
+
execSync(`npx @tailwindcss/cli -i "${inputFile}" -o "${outputFile}" --minify`, {
|
|
1835
|
+
timeout: 3e4,
|
|
1836
|
+
stdio: "pipe"
|
|
1837
|
+
});
|
|
1838
|
+
cssContent = fs.readFileSync(outputFile, "utf-8");
|
|
1839
|
+
fs.unlinkSync(inputFile);
|
|
1840
|
+
fs.unlinkSync(outputFile);
|
|
1841
|
+
console.log(`[JXR] Compiled Tailwind CSS for ${vfsPath}`);
|
|
1842
|
+
} catch {
|
|
1843
|
+
const js2 = `
|
|
1844
|
+
const tailwindScript = document.createElement('script');
|
|
1845
|
+
tailwindScript.src = 'https://cdn.tailwindcss.com';
|
|
1846
|
+
tailwindScript.onload = function() {
|
|
1847
|
+
const style = document.createElement('style');
|
|
1848
|
+
style.textContent = \`${file.content.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$")}\`;
|
|
1849
|
+
document.head.appendChild(style);
|
|
1850
|
+
};
|
|
1851
|
+
document.head.appendChild(tailwindScript);
|
|
1852
|
+
export default \`${file.content.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$")}\`;
|
|
1853
|
+
`;
|
|
1854
|
+
res.writeHead(200, {
|
|
1855
|
+
"Content-Type": "application/javascript",
|
|
1856
|
+
"Cache-Control": "no-cache"
|
|
1857
|
+
});
|
|
1858
|
+
res.end(js2);
|
|
1859
|
+
return;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
} catch (error) {
|
|
1863
|
+
console.warn(`[JXR] Tailwind handling error: ${error?.message || error}`);
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
const escapedCSS = cssContent.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
|
|
1819
1867
|
const js = `
|
|
1820
1868
|
const style = document.createElement('style');
|
|
1821
1869
|
style.textContent = \`${escapedCSS}\`;
|
|
@@ -1949,7 +1997,14 @@ export default \`${escapedCSS}\`;
|
|
|
1949
1997
|
<head>
|
|
1950
1998
|
<meta charset="UTF-8">
|
|
1951
1999
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1952
|
-
<title>JXR
|
|
2000
|
+
<title>JXR.js \u2014 Edge OS Runtime Framework</title>
|
|
2001
|
+
<meta name="description" content="JXR.js is the next-generation edge runtime framework for React Native and React. MoQ transport, Web Crypto, Worker pools.">
|
|
2002
|
+
|
|
2003
|
+
<!-- Google Fonts -->
|
|
2004
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
2005
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
2006
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
2007
|
+
|
|
1953
2008
|
<script type="importmap">
|
|
1954
2009
|
${JSON.stringify(importMap)}
|
|
1955
2010
|
<\/script>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jxr-server-manager.d.ts","sourceRoot":"","sources":["../src/jxr-server-manager.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,QAAQ,CAAoD;IACpE,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,OAAO,CAAuC;gBAE1C,MAAM,GAAE,eAAoB;IAYlC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YASnB,gBAAgB;IAoC9B,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,cAAc;YAUR,qBAAqB;IA2BnC,OAAO,CAAC,eAAe;IAOjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"jxr-server-manager.d.ts","sourceRoot":"","sources":["../src/jxr-server-manager.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,QAAQ,CAAoD;IACpE,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,OAAO,CAAuC;gBAE1C,MAAM,GAAE,eAAoB;IAYlC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YASnB,gBAAgB;IAoC9B,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,cAAc;YAUR,qBAAqB;IA2BnC,OAAO,CAAC,eAAe;IAOjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmLtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA+B3B,OAAO,CAAC,YAAY;CAsHrB"}
|
package/package.json
CHANGED
|
@@ -249,7 +249,63 @@ export class JXRServerManager {
|
|
|
249
249
|
|
|
250
250
|
// Serve CSS files as JavaScript that injects the CSS
|
|
251
251
|
if (vfsPath.endsWith('.css')) {
|
|
252
|
-
|
|
252
|
+
let cssContent = file.content;
|
|
253
|
+
|
|
254
|
+
// Check for pre-compiled Tailwind CSS first
|
|
255
|
+
if (vfsPath === '/src/index.css') {
|
|
256
|
+
try {
|
|
257
|
+
const fs = await import('fs');
|
|
258
|
+
const compiledPath = path.join(process.cwd(), 'src', 'index.compiled.css');
|
|
259
|
+
if (fs.existsSync(compiledPath)) {
|
|
260
|
+
cssContent = fs.readFileSync(compiledPath, 'utf-8');
|
|
261
|
+
console.log(`[JXR] Using pre-compiled Tailwind CSS from index.compiled.css`);
|
|
262
|
+
} else {
|
|
263
|
+
// Try to compile on-the-fly
|
|
264
|
+
const { execSync } = await import('child_process');
|
|
265
|
+
const os = await import('os');
|
|
266
|
+
|
|
267
|
+
const tmpDir = os.tmpdir();
|
|
268
|
+
const inputFile = path.join(tmpDir, `jxr-tailwind-${Date.now()}.css`);
|
|
269
|
+
const outputFile = path.join(tmpDir, `jxr-tailwind-${Date.now()}.compiled.css`);
|
|
270
|
+
|
|
271
|
+
fs.writeFileSync(inputFile, cssContent);
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
execSync(`npx @tailwindcss/cli -i "${inputFile}" -o "${outputFile}" --minify`, {
|
|
275
|
+
timeout: 30000,
|
|
276
|
+
stdio: 'pipe'
|
|
277
|
+
});
|
|
278
|
+
cssContent = fs.readFileSync(outputFile, 'utf-8');
|
|
279
|
+
fs.unlinkSync(inputFile);
|
|
280
|
+
fs.unlinkSync(outputFile);
|
|
281
|
+
console.log(`[JXR] Compiled Tailwind CSS for ${vfsPath}`);
|
|
282
|
+
} catch {
|
|
283
|
+
// CDN fallback
|
|
284
|
+
const js = `
|
|
285
|
+
const tailwindScript = document.createElement('script');
|
|
286
|
+
tailwindScript.src = 'https://cdn.tailwindcss.com';
|
|
287
|
+
tailwindScript.onload = function() {
|
|
288
|
+
const style = document.createElement('style');
|
|
289
|
+
style.textContent = \`${file.content.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$')}\`;
|
|
290
|
+
document.head.appendChild(style);
|
|
291
|
+
};
|
|
292
|
+
document.head.appendChild(tailwindScript);
|
|
293
|
+
export default \`${file.content.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$')}\`;
|
|
294
|
+
`;
|
|
295
|
+
res.writeHead(200, {
|
|
296
|
+
"Content-Type": "application/javascript",
|
|
297
|
+
"Cache-Control": "no-cache"
|
|
298
|
+
});
|
|
299
|
+
res.end(js);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
} catch (error: any) {
|
|
304
|
+
console.warn(`[JXR] Tailwind handling error: ${error?.message || error}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const escapedCSS = cssContent
|
|
253
309
|
.replace(/\\/g, '\\\\')
|
|
254
310
|
.replace(/`/g, '\\`')
|
|
255
311
|
.replace(/\$/g, '\\$');
|
|
@@ -411,7 +467,14 @@ export default \`${escapedCSS}\`;
|
|
|
411
467
|
<head>
|
|
412
468
|
<meta charset="UTF-8">
|
|
413
469
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
414
|
-
<title>JXR
|
|
470
|
+
<title>JXR.js — Edge OS Runtime Framework</title>
|
|
471
|
+
<meta name="description" content="JXR.js is the next-generation edge runtime framework for React Native and React. MoQ transport, Web Crypto, Worker pools.">
|
|
472
|
+
|
|
473
|
+
<!-- Google Fonts -->
|
|
474
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
475
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
476
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
477
|
+
|
|
415
478
|
<script type="importmap">
|
|
416
479
|
${JSON.stringify(importMap)}
|
|
417
480
|
</script>
|
|
@@ -1,160 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
/**
|
|
2
|
+
* JXR.js Marketing Website — App.tsx
|
|
3
|
+
* LavaFlow OS Design System
|
|
4
|
+
* Powered by JXR Studios × DamascusAI
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Toaster } from "@/components/ui/sonner";
|
|
8
|
+
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
9
|
+
import { Route, Switch } from "wouter";
|
|
10
|
+
import ErrorBoundary from "./components/ErrorBoundary";
|
|
11
|
+
import { ThemeProvider } from "./contexts/ThemeContext";
|
|
12
|
+
import Home from "./pages/Home";
|
|
13
|
+
import DocsPage from "./pages/Docs";
|
|
14
|
+
import NotFound from "./pages/NotFound";
|
|
15
|
+
|
|
16
|
+
function Router() {
|
|
17
|
+
return (
|
|
18
|
+
<Switch>
|
|
19
|
+
<Route path="/" component={Home} />
|
|
20
|
+
<Route path="/docs" component={DocsPage} />
|
|
21
|
+
<Route path="/docs/:section" component={DocsPage} />
|
|
22
|
+
<Route component={NotFound} />
|
|
23
|
+
</Switch>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
9
26
|
|
|
10
27
|
export default function App() {
|
|
11
|
-
const [count, setCount] = useState(0)
|
|
12
|
-
|
|
13
28
|
return (
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
{/* Hero Card */}
|
|
26
|
-
<div style={{
|
|
27
|
-
background: 'rgba(255,255,255,0.05)',
|
|
28
|
-
backdropFilter: 'blur(20px)',
|
|
29
|
-
borderRadius: '1.5rem',
|
|
30
|
-
border: '1px solid rgba(255,255,255,0.1)',
|
|
31
|
-
padding: '3rem',
|
|
32
|
-
maxWidth: '640px',
|
|
33
|
-
width: '100%',
|
|
34
|
-
textAlign: 'center',
|
|
35
|
-
boxShadow: '0 25px 50px -12px rgba(0,0,0,0.5)',
|
|
36
|
-
}}>
|
|
37
|
-
{/* Logo */}
|
|
38
|
-
<div style={{
|
|
39
|
-
width: '64px',
|
|
40
|
-
height: '64px',
|
|
41
|
-
borderRadius: '16px',
|
|
42
|
-
background: 'linear-gradient(135deg, #6366f1, #a855f7, #ec4899)',
|
|
43
|
-
display: 'flex',
|
|
44
|
-
alignItems: 'center',
|
|
45
|
-
justifyContent: 'center',
|
|
46
|
-
margin: '0 auto 1.5rem',
|
|
47
|
-
fontSize: '1.5rem',
|
|
48
|
-
fontWeight: 'bold',
|
|
49
|
-
color: 'white',
|
|
50
|
-
boxShadow: '0 0 30px rgba(99,102,241,0.4)',
|
|
51
|
-
}}>
|
|
52
|
-
x0
|
|
53
|
-
</div>
|
|
54
|
-
|
|
55
|
-
<h1 style={{
|
|
56
|
-
fontSize: '2.25rem',
|
|
57
|
-
fontWeight: 800,
|
|
58
|
-
marginBottom: '0.75rem',
|
|
59
|
-
background: 'linear-gradient(135deg, #c7d2fe, #e9d5ff, #fbcfe8)',
|
|
60
|
-
WebkitBackgroundClip: 'text',
|
|
61
|
-
WebkitTextFillColor: 'transparent',
|
|
62
|
-
lineHeight: 1.2,
|
|
63
|
-
}}>
|
|
64
|
-
Your App is Live
|
|
65
|
-
</h1>
|
|
66
|
-
|
|
67
|
-
<p style={{
|
|
68
|
-
fontSize: '1.1rem',
|
|
69
|
-
color: 'rgba(226,232,240,0.7)',
|
|
70
|
-
marginBottom: '2rem',
|
|
71
|
-
lineHeight: 1.6,
|
|
72
|
-
}}>
|
|
73
|
-
This project is ready for development. Use the AI chat to describe
|
|
74
|
-
what you want to build, or start editing files directly.
|
|
75
|
-
</p>
|
|
76
|
-
|
|
77
|
-
{/* Interactive Counter */}
|
|
78
|
-
<div style={{
|
|
79
|
-
display: 'flex',
|
|
80
|
-
alignItems: 'center',
|
|
81
|
-
justifyContent: 'center',
|
|
82
|
-
gap: '1rem',
|
|
83
|
-
marginBottom: '2.5rem',
|
|
84
|
-
}}>
|
|
85
|
-
<button
|
|
86
|
-
onClick={() => setCount(c => c - 1)}
|
|
87
|
-
style={{
|
|
88
|
-
width: '40px', height: '40px', borderRadius: '12px',
|
|
89
|
-
background: 'rgba(255,255,255,0.1)', border: '1px solid rgba(255,255,255,0.15)',
|
|
90
|
-
color: '#e2e8f0', fontSize: '1.25rem', cursor: 'pointer',
|
|
91
|
-
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
92
|
-
transition: 'all 0.15s',
|
|
93
|
-
}}
|
|
94
|
-
onMouseEnter={e => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}
|
|
95
|
-
onMouseLeave={e => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}
|
|
96
|
-
>
|
|
97
|
-
−
|
|
98
|
-
</button>
|
|
99
|
-
<div style={{
|
|
100
|
-
padding: '0.5rem 1.5rem',
|
|
101
|
-
borderRadius: '12px',
|
|
102
|
-
background: 'rgba(99,102,241,0.2)',
|
|
103
|
-
border: '1px solid rgba(99,102,241,0.3)',
|
|
104
|
-
fontSize: '1.25rem',
|
|
105
|
-
fontWeight: 700,
|
|
106
|
-
fontVariantNumeric: 'tabular-nums',
|
|
107
|
-
minWidth: '80px',
|
|
108
|
-
}}>
|
|
109
|
-
{count}
|
|
110
|
-
</div>
|
|
111
|
-
<button
|
|
112
|
-
onClick={() => setCount(c => c + 1)}
|
|
113
|
-
style={{
|
|
114
|
-
width: '40px', height: '40px', borderRadius: '12px',
|
|
115
|
-
background: 'linear-gradient(135deg, #6366f1, #a855f7)',
|
|
116
|
-
border: 'none', color: 'white', fontSize: '1.25rem', cursor: 'pointer',
|
|
117
|
-
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
118
|
-
boxShadow: '0 0 20px rgba(99,102,241,0.3)',
|
|
119
|
-
transition: 'all 0.15s',
|
|
29
|
+
<ErrorBoundary>
|
|
30
|
+
<ThemeProvider defaultTheme="dark">
|
|
31
|
+
<TooltipProvider>
|
|
32
|
+
<Toaster
|
|
33
|
+
theme="dark"
|
|
34
|
+
toastOptions={{
|
|
35
|
+
style: {
|
|
36
|
+
background: 'oklch(0.13 0.007 285)',
|
|
37
|
+
border: '1px solid oklch(1 0 0 / 10%)',
|
|
38
|
+
color: 'oklch(0.93 0.005 65)',
|
|
39
|
+
},
|
|
120
40
|
}}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
{/* Feature Grid */}
|
|
129
|
-
<div style={{
|
|
130
|
-
display: 'grid',
|
|
131
|
-
gridTemplateColumns: 'repeat(2, 1fr)',
|
|
132
|
-
gap: '0.75rem',
|
|
133
|
-
textAlign: 'left',
|
|
134
|
-
}}>
|
|
135
|
-
{FEATURES.map((f) => (
|
|
136
|
-
<div key={f.title} style={{
|
|
137
|
-
padding: '1rem',
|
|
138
|
-
borderRadius: '12px',
|
|
139
|
-
background: 'rgba(255,255,255,0.04)',
|
|
140
|
-
border: '1px solid rgba(255,255,255,0.06)',
|
|
141
|
-
}}>
|
|
142
|
-
<div style={{ fontSize: '1.25rem', marginBottom: '0.25rem' }}>{f.icon}</div>
|
|
143
|
-
<div style={{ fontWeight: 600, fontSize: '0.875rem', marginBottom: '0.25rem' }}>{f.title}</div>
|
|
144
|
-
<div style={{ fontSize: '0.75rem', color: 'rgba(226,232,240,0.5)', lineHeight: 1.4 }}>{f.desc}</div>
|
|
145
|
-
</div>
|
|
146
|
-
))}
|
|
147
|
-
</div>
|
|
148
|
-
</div>
|
|
149
|
-
|
|
150
|
-
{/* Footer */}
|
|
151
|
-
<p style={{
|
|
152
|
-
marginTop: '2rem',
|
|
153
|
-
fontSize: '0.8rem',
|
|
154
|
-
color: 'rgba(226,232,240,0.3)',
|
|
155
|
-
}}>
|
|
156
|
-
Built with x0 · React 19 · TypeScript · Tailwind CSS
|
|
157
|
-
</p>
|
|
158
|
-
</div>
|
|
159
|
-
)
|
|
160
|
-
}
|
|
41
|
+
/>
|
|
42
|
+
<Router />
|
|
43
|
+
</TooltipProvider>
|
|
44
|
+
</ThemeProvider>
|
|
45
|
+
</ErrorBoundary>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { cn } from "@/lib/utils";
|
|
2
|
+
import { AlertTriangle, RotateCcw } from "lucide-react";
|
|
3
|
+
import { Component, ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface State {
|
|
10
|
+
hasError: boolean;
|
|
11
|
+
error: Error | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class ErrorBoundary extends Component<Props, State> {
|
|
15
|
+
constructor(props: Props) {
|
|
16
|
+
super(props);
|
|
17
|
+
this.state = { hasError: false, error: null };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static getDerivedStateFromError(error: Error): State {
|
|
21
|
+
return { hasError: true, error };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
render() {
|
|
25
|
+
if (this.state.hasError) {
|
|
26
|
+
return (
|
|
27
|
+
<div className="flex items-center justify-center min-h-screen p-8 bg-background">
|
|
28
|
+
<div className="flex flex-col items-center w-full max-w-2xl p-8">
|
|
29
|
+
<AlertTriangle
|
|
30
|
+
size={48}
|
|
31
|
+
className="text-destructive mb-6 flex-shrink-0"
|
|
32
|
+
/>
|
|
33
|
+
|
|
34
|
+
<h2 className="text-xl mb-4">An unexpected error occurred.</h2>
|
|
35
|
+
|
|
36
|
+
<div className="p-4 w-full rounded bg-muted overflow-auto mb-6">
|
|
37
|
+
<pre className="text-sm text-muted-foreground whitespace-break-spaces">
|
|
38
|
+
{this.state.error?.stack}
|
|
39
|
+
</pre>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<button
|
|
43
|
+
onClick={() => window.location.reload()}
|
|
44
|
+
className={cn(
|
|
45
|
+
"flex items-center gap-2 px-4 py-2 rounded-lg",
|
|
46
|
+
"bg-primary text-primary-foreground",
|
|
47
|
+
"hover:opacity-90 cursor-pointer"
|
|
48
|
+
)}
|
|
49
|
+
>
|
|
50
|
+
<RotateCcw size={16} />
|
|
51
|
+
Reload Page
|
|
52
|
+
</button>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return this.props.children;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export default ErrorBoundary;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
import {
|
|
5
|
+
Dialog,
|
|
6
|
+
DialogContent,
|
|
7
|
+
DialogDescription,
|
|
8
|
+
DialogFooter,
|
|
9
|
+
DialogTitle,
|
|
10
|
+
} from "@/components/ui/dialog";
|
|
11
|
+
|
|
12
|
+
interface ManusDialogProps {
|
|
13
|
+
title?: string;
|
|
14
|
+
logo?: string;
|
|
15
|
+
open?: boolean;
|
|
16
|
+
onLogin: () => void;
|
|
17
|
+
onOpenChange?: (open: boolean) => void;
|
|
18
|
+
onClose?: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function ManusDialog({
|
|
22
|
+
title,
|
|
23
|
+
logo,
|
|
24
|
+
open = false,
|
|
25
|
+
onLogin,
|
|
26
|
+
onOpenChange,
|
|
27
|
+
onClose,
|
|
28
|
+
}: ManusDialogProps) {
|
|
29
|
+
const [internalOpen, setInternalOpen] = useState(open);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!onOpenChange) {
|
|
33
|
+
setInternalOpen(open);
|
|
34
|
+
}
|
|
35
|
+
}, [open, onOpenChange]);
|
|
36
|
+
|
|
37
|
+
const handleOpenChange = (nextOpen: boolean) => {
|
|
38
|
+
if (onOpenChange) {
|
|
39
|
+
onOpenChange(nextOpen);
|
|
40
|
+
} else {
|
|
41
|
+
setInternalOpen(nextOpen);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!nextOpen) {
|
|
45
|
+
onClose?.();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Dialog
|
|
51
|
+
open={onOpenChange ? open : internalOpen}
|
|
52
|
+
onOpenChange={handleOpenChange}
|
|
53
|
+
>
|
|
54
|
+
<DialogContent className="py-5 bg-[#f8f8f7] rounded-[20px] w-[400px] shadow-[0px_4px_11px_0px_rgba(0,0,0,0.08)] border border-[rgba(0,0,0,0.08)] backdrop-blur-2xl p-0 gap-0 text-center">
|
|
55
|
+
<div className="flex flex-col items-center gap-2 p-5 pt-12">
|
|
56
|
+
{logo ? (
|
|
57
|
+
<div className="w-16 h-16 bg-white rounded-xl border border-[rgba(0,0,0,0.08)] flex items-center justify-center">
|
|
58
|
+
<img src={logo} alt="Dialog graphic" className="w-10 h-10 rounded-md" />
|
|
59
|
+
</div>
|
|
60
|
+
) : null}
|
|
61
|
+
|
|
62
|
+
{/* Title and subtitle */}
|
|
63
|
+
{title ? (
|
|
64
|
+
<DialogTitle className="text-xl font-semibold text-[#34322d] leading-[26px] tracking-[-0.44px]">
|
|
65
|
+
{title}
|
|
66
|
+
</DialogTitle>
|
|
67
|
+
) : null}
|
|
68
|
+
<DialogDescription className="text-sm text-[#858481] leading-5 tracking-[-0.154px]">
|
|
69
|
+
Please login with Manus to continue
|
|
70
|
+
</DialogDescription>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<DialogFooter className="px-5 py-5">
|
|
74
|
+
{/* Login button */}
|
|
75
|
+
<Button
|
|
76
|
+
onClick={onLogin}
|
|
77
|
+
className="w-full h-10 bg-[#1a1a19] hover:bg-[#1a1a19]/90 text-white rounded-[10px] text-sm font-medium leading-5 tracking-[-0.154px]"
|
|
78
|
+
>
|
|
79
|
+
Login with Manus
|
|
80
|
+
</Button>
|
|
81
|
+
</DialogFooter>
|
|
82
|
+
</DialogContent>
|
|
83
|
+
</Dialog>
|
|
84
|
+
);
|
|
85
|
+
}
|