Skip to content

Commit 42de1af

Browse files
v1.1.0 desktop playground
1 parent afcec91 commit 42de1af

File tree

15 files changed

+503
-407
lines changed

15 files changed

+503
-407
lines changed

bjs-playground/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "bjs-playground",
33
"private": true,
4-
"version": "0.0.0",
4+
"version": "0.0.1",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

bjs-playground/public/Npm-logo.svg

Lines changed: 8 additions & 0 deletions
Loading

bjs-playground/src/App.tsx

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import { useState } from "react";
3+
import { useState, useRef } from "react";
44
import { motion } from "framer-motion";
55
import { ExamplesBar } from "./components/playground/ExamplesBar";
66
import { ActionButtons } from "./components/playground/ActionButtons";
@@ -93,34 +93,31 @@ export default function PlaygroundPage() {
9393
setExecutionTime(null);
9494
};
9595

96+
const runCode = () => {
97+
handleRun(banglaCode, (out, js) => { setOutput(out); setJsCode(js); }, setError);
98+
};
99+
96100
return (
97101
<div className="min-h-screen bg-white dark:bg-gradient-to-br from-gray-900 to-gray-800">
98102
{/* Header */}
99103
<header className="border-b border-gray-700 bg-white dark:bg-gray-900/80 backdrop-blur-md sticky top-0 z-50">
100104
<div className="container mx-auto px-4 py-4">
101105
<div className="flex items-center justify-between">
102-
<div className="flex items-center gap-4">
103-
<div className="h-10 w-10 bg-black rounded-lg flex items-center justify-center shadow-lg shadow-blue-500/30">
104-
<span className="text-white text-lg font-bold"></span>
105-
</div>
106+
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
106107
<div>
107108
<h1 className="text-2xl font-bold bg-gradient-to-r from-gray-900 to-gray-700 bg-clip-text text-transparent dark:from-gray-100 dark:to-gray-300">
108-
BanglaScript Playground <span title="Version 1" className="shadow underline decoration-blue-500">[v1]</span>
109+
BanglaScript Playground
109110
</h1>
110111
<p className="text-sm text-gray-800 dark:text-gray-300">
111-
<a href="https://bangla-script.vercel.app/" target="_blank" rel="noopener noreferrer">
112-
বাংলায় প্রোগ্রামিং করুন •
113-
</a>
114-
<a href="https://www.npmjs.com/package/banglascript" target="_blank" rel="noopener noreferrer" className="ml-1 text-blue-400 hover:underline">
115-
NPM প্যাকেজ দেখুন
116-
</a>
112+
বাংলায় প্রোগ্রামিং করুন
117113
</p>
118114
</div>
119115
</div>
120-
<div className="flex items-center gap-2">
121-
<span className="px-3 py-1 bg-yellow-900/90 text-yellow-300 text-xs font-medium rounded-full border border-yellow-600/80 shadow">
122-
⚠️ ডেভেলপমেন্ট মোড
123-
</span>
116+
<div className="text-center items-center gap-2">
117+
<a href="https://www.npmjs.com/package/banglascript" target="_blank" rel="noopener noreferrer" className="flex text-blue-400 hover:underline">
118+
<img src="/Npm-logo.svg" alt="Npm Logo" className="w-10 h-auto mr-1"/>
119+
প্যাকেজ দেখুন
120+
</a>
124121
</div>
125122
</div>
126123
</div>
@@ -145,9 +142,9 @@ export default function PlaygroundPage() {
145142
transition={{ delay: 0.2 }}
146143
>
147144
<div className="mb-4 flex items-center gap-3">
148-
<div className="h-8 w-8 bg-black rounded-lg flex items-center justify-center shadow-md shadow-[#F7DF1E]">
149-
<span className="text-white text-sm font-bold"></span>
150-
</div>
145+
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary">
146+
<span className="font-mono text-lg font-bold text-primary-foreground"></span>
147+
</div>
151148
<h2 className="text-lg font-bold text-gray-600 dark:text-gray-100">BanglaScript Code</h2>
152149
</div>
153150
<div className="h-[650px]">
@@ -167,6 +164,7 @@ export default function PlaygroundPage() {
167164
output={output}
168165
error={error}
169166
executionTime={executionTime}
167+
runCode={runCode}
170168
/>
171169
</motion.div>
172170
</div>

bjs-playground/src/components/playground/ActionButtons.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,13 @@ export function ActionButtons({
3030
initial={{ opacity: 0, y: -10 }}
3131
animate={{ opacity: 1, y: 0 }}
3232
transition={{ delay: 0.1 }}
33-
className="mb-6 flex flex-wrap items-center justify-between gap-4 bg-gradient-to-r from-gray-800 to-gray-900 p-3 sm:p-4 rounded-xl border border-gray-700/50 shadow-lg backdrop-blur-sm"
33+
className="mb-6 flex flex-wrap items-center justify-between gap-4
34+
bg-gradient-to-r from-gray-900 to-green-900
35+
dark:bg-gradient-to-r dark:from-gray-800 dark:to-gray-900
36+
p-3 sm:p-4 rounded-xl border border-gray-700/50
37+
shadow-lg backdrop-blur-sm"
3438
>
39+
3540
{/* Left Group: Contains all action buttons */}
3641
<div className="flex flex-wrap items-center gap-3 p-2">
3742
<Button

bjs-playground/src/components/playground/BanglaCodeEditor.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,6 @@ export default function BanglaCodeEditor({ value = '', onChange }: CodeEditorPro
346346
isFullscreen ? 'fixed inset-4 z-50' : 'h-full'
347347
}`}
348348
>
349-
{/* Enhanced Top Bar */}
350349
<div className="flex-shrink-0 bg-gradient-to-r from-[#2d2d30] to-[#252526] border-b border-gray-800 px-4 py-2 flex items-center justify-between">
351350
<div className="flex items-center gap-3">
352351
<div className="flex items-center gap-2">
@@ -467,7 +466,7 @@ export default function BanglaCodeEditor({ value = '', onChange }: CodeEditorPro
467466
{/* Enhanced Line Numbers */}
468467
<div
469468
ref={lineNumbersRef}
470-
className="flex-shrink-0 bg-[#1e1e1e] text-right select-none border-r border-gray-800 overflow-y-auto min-w-[4rem]"
469+
className="flex-shrink-0 pt-4 bg-[#1e1e1e] text-right select-none border-r border-gray-800 overflow-y-auto min-w-[4rem]"
471470
style={{
472471
scrollbarWidth: 'none',
473472
msOverflowStyle: 'none',
Lines changed: 149 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,165 @@
1-
import { motion, AnimatePresence } from "framer-motion";
2-
import { Terminal } from "lucide-react";
1+
import { useState, useRef, useEffect } from "react";
2+
import { motion, } from "framer-motion";
3+
import { Terminal, RefreshCw } from "lucide-react";
34
import CommandDisplay from "../CommandDisplay";
45

56
interface ConsoleOutputProps {
67
output: string;
78
error: string;
89
executionTime?: number | null;
10+
runCode?: () => void;
911
}
1012

11-
export function ConsoleOutput({ output, error, executionTime }: ConsoleOutputProps) {
13+
type HistoryItem = {
14+
type: "command" | "output" | "error" | "info";
15+
text: string;
16+
};
17+
18+
export function ConsoleOutput({ output, error, executionTime, runCode }: ConsoleOutputProps) {
19+
const [terminalHistory, setTerminalHistory] = useState<HistoryItem[]>([]);
20+
const [currentInput, setCurrentInput] = useState("");
21+
const contentRef = useRef<HTMLDivElement>(null);
22+
23+
useEffect(() => {
24+
if (contentRef.current) {
25+
contentRef.current.scrollTop = contentRef.current.scrollHeight;
26+
}
27+
}, [terminalHistory, currentInput]);
28+
29+
useEffect(() => {
30+
if (output) {
31+
setTerminalHistory((prev) => [
32+
...prev,
33+
{ type: "output", text: output },
34+
{ type: "info", text: `✓ Executed in ${executionTime?.toFixed(2) ?? 0}ms` },
35+
]);
36+
}
37+
}, [output, executionTime]);
38+
39+
useEffect(() => {
40+
if (error) {
41+
setTerminalHistory((prev) => [
42+
...prev,
43+
{ type: "error", text: error },
44+
{ type: "info", text: "✗ Process exited with code 1" },
45+
]);
46+
}
47+
}, [error]);
48+
49+
const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
50+
e.preventDefault();
51+
if (e.key === "Enter") {
52+
const trimmed = currentInput.trim();
53+
setTerminalHistory((prev) => [...prev, { type: "command", text: trimmed }]);
54+
if (trimmed === "node main.js" || trimmed === "deno run main.js" || trimmed === "bjs run main.bjs") {
55+
setTerminalHistory((prev) => [...prev, { type: "info", text: "Running..." }]);
56+
runCode?.();
57+
} else if (trimmed === "clear") {
58+
setTerminalHistory([]);
59+
} else if (trimmed) {
60+
setTerminalHistory((prev) => [...prev, { type: "error", text: `command not found: ${trimmed}` }]);
61+
}
62+
setCurrentInput("");
63+
return;
64+
}
65+
if (e.key === "Backspace") {
66+
setCurrentInput((prev) => prev.slice(0, -1));
67+
return;
68+
}
69+
if (e.key.length === 1 && !e.ctrlKey && !e.metaKey) {
70+
setCurrentInput((prev) => prev + e.key);
71+
return;
72+
}
73+
};
74+
1275
return (
13-
<div className="h-full flex flex-col bg-[#0a0a0a] font-mono text-sm">
14-
<AnimatePresence mode="wait">
15-
{error ? (
16-
<motion.div
17-
key="error"
18-
initial={{ opacity: 0, y: 10 }}
19-
animate={{ opacity: 1, y: 0 }}
20-
exit={{ opacity: 0, y: -10 }}
21-
transition={{ duration: 0.2 }}
22-
className="flex-1 overflow-y-auto p-4 space-y-2"
23-
>
24-
<div className="flex items-center gap-2 text-gray-400 text-xs mb-3 ">
25-
<span className="text-emerald-500"></span>
26-
<span className="text-cyan-400">~/banglascript</span>
27-
<span className="text-gray-500">$</span>
28-
<span className="text-gray-300">node script.js</span>
29-
</div>
30-
<div className="bg-red-950/20 border-l-4 border-red-500 p-3 rounded-r">
31-
<div className="flex items-center gap-2 mb-2">
32-
<span className="text-red-400 text-lg"></span>
33-
<span className="text-red-400 font-semibold">Runtime Error</span>
76+
<div className="h-full flex flex-col bg-[#0d0d0d] font-mono text-sm relative">
77+
{/* Terminal Header Bar */}
78+
<div className="bg-[#1a1a1a] border-b border-gray-800 px-4 py-2 flex items-center gap-2 select-none">
79+
<div className="flex gap-1.5">
80+
<div className="w-3 h-3 rounded-full bg-red-500/80 cursor-pointer hover:brightness-110 transition-all"></div>
81+
<div className="w-3 h-3 rounded-full bg-yellow-500/80 cursor-pointer hover:brightness-110 transition-all"></div>
82+
<div
83+
className="w-3 h-3 rounded-full bg-green-500/80 cursor-pointer hover:brightness-110 transition-all"
84+
></div>
85+
</div>
86+
<div className="flex-1 flex items-center justify-center gap-2 text-xs">
87+
<Terminal className="h-3.5 w-3.5 text-amber-100" />
88+
<span className="text-gray-500">BanglaScript Terminal</span>
89+
</div>
90+
<div className="flex items-center justify-end w-16 pr-4"
91+
title="Clear the terminal."
92+
>
93+
<RefreshCw
94+
95+
className="h-4 w-4 text-gray-500 hover:text-gray-300 cursor-pointer"
96+
onClick={() => setTerminalHistory([])}
97+
/>
98+
</div>
99+
</div>
100+
101+
{/* Terminal Content */}
102+
<div
103+
ref={contentRef}
104+
tabIndex={0}
105+
onKeyDown={handleKeyDown}
106+
onClick={() => contentRef.current?.focus()}
107+
className="flex-1 overflow-y-auto p-4 space-y-2 outline-none"
108+
style={{
109+
scrollbarWidth: "thin",
110+
scrollbarColor: "#374151 #1a1a1a",
111+
}}
112+
>
113+
{terminalHistory.length === 0 && (
114+
<>
115+
<div className="text-gray-600 text-[13px]">BanglaScript Terminal v1.3.7</div>
116+
<div className="text-gray-700 text-xs">Type commands like '
117+
<span className="text-gray-50/25">node main.js</span>' or '
118+
<span className="text-gray-50/25">deno run main.js</span>' to run the code | run `
119+
<span className="text-gray-50/25">clear</span>` to clean the terminal
34120
</div>
35-
<pre className="text-red-300 whitespace-pre-wrap leading-relaxed text-xs">
36-
{error}
37-
</pre>
38-
</div>
39-
<div className="flex items-center gap-2 text-gray-500 text-xs pt-2">
40-
<span className="text-red-500"></span>
41-
<span>Process exited with code 1</span>
42-
</div>
43-
</motion.div>
44-
) : output ? (
45-
<motion.div
46-
key="output"
47-
initial={{ opacity: 0, y: 10 }}
48-
animate={{ opacity: 1, y: 0 }}
49-
exit={{ opacity: 0, y: -10 }}
50-
transition={{ duration: 0.2 }}
51-
className="flex-1 overflow-y-scroll p-4 space-y-2"
52-
style={{
53-
scrollbarWidth: 'thin',
54-
scrollbarColor: '#eeeee'
55-
}}
56-
>
57-
<div className="flex items-center gap-2 text-gray-400 text-xs mb-3">
58-
<span className="text-emerald-500"></span>
59-
<span className="text-cyan-400">~/banglascript</span>
60-
<span className="text-gray-500">$</span>
61-
<CommandDisplay/>
62-
</div>
63-
<div className="bg-gray-900/30 border border-green-800/50 rounded p-3">
64-
<pre className="text-gray-100 whitespace-pre-wrap leading-relaxed text-xs">
65-
{output}
66-
</pre>
67-
</div>
68-
<div className="flex items-center gap-2 text-gray-500 text-xs pt-2">
69-
<span className="text-emerald-500"></span>
70-
<span>Process completed successfully in {executionTime?.toFixed(2)}ms</span>
71-
</div>
72-
</motion.div>
73-
) : (
74-
<motion.div
75-
key="empty"
76-
initial={{ opacity: 0 }}
77-
animate={{ opacity: 1 }}
78-
exit={{ opacity: 0 }}
79-
className="h-full flex flex-col p-4"
80-
>
81-
<div className="space-y-2 mb-4">
82-
<div className="flex items-center gap-2 text-gray-600 text-xs">
83-
<Terminal className="h-3.5 w-3.5" />
84-
<span>BanglaScript Terminal v1.0.0</span>
121+
<div className="w-full border-t border-gray-800/50 my-2"></div>
122+
</>
123+
)}
124+
125+
{terminalHistory.map((item, index) => (
126+
<div key={index}>
127+
{item.type === "command" && (
128+
<div className="flex items-center gap-2 text-[13px]">
129+
<span className="text-emerald-400"></span>
130+
<span className="text-sky-400">~/banglascript</span>
131+
<span className="text-green-600">$</span>
132+
<span className="text-gray-300">{item.text}</span>
85133
</div>
86-
<div className="w-full border-t border-gray-800/50"></div>
87-
<div className="flex items-center gap-2 text-gray-500 text-xs">
88-
<span className="text-emerald-500"></span>
89-
<span className="text-cyan-400">~/banglascript</span>
90-
<span className="text-gray-600">$</span>
91-
<motion.span
92-
className="inline-block w-2 h-4 bg-gray-500 ml-1"
93-
animate={{ opacity: [1, 0, 1] }}
94-
transition={{ duration: 1, repeat: Infinity }}
95-
/>
134+
)}
135+
{item.type === "output" && (
136+
<div className="text-gray-200 text-[13px] leading-relaxed mt-2 bg-gray-900/30 border border-green-800/50 rounded p-3">
137+
<pre className="whitespace-pre-wrap">{item.text}</pre>
96138
</div>
97-
</div>
98-
<div className="flex-1 flex flex-col items-center justify-center text-gray-500">
99-
<div className="relative mb-6">
100-
<Terminal className="h-16 w-16 opacity-20 text-cyan-400" />
101-
<motion.div
102-
className="absolute inset-0 bg-cyan-500/10 blur-xl rounded-full"
103-
animate={{ scale: [1, 1.2, 1] }}
104-
transition={{ duration: 3, repeat: Infinity }}
105-
/>
139+
)}
140+
{item.type === "error" && (
141+
<div className="text-red-400 text-[13px] mt-2">
142+
<pre className="whitespace-pre-wrap">{item.text}</pre>
106143
</div>
107-
<p className="text-center">
108-
<span className="text-gray-400 font-medium block mb-1">কোড রান করতে "কোড চালান" বাটনে ক্লিক করুন</span>
109-
<span className="text-xs text-gray-600">Waiting for execution...</span>
110-
</p>
111-
</div>
112-
</motion.div>
113-
)}
114-
</AnimatePresence>
144+
)}
145+
{item.type === "info" && (
146+
<div className="text-green-600 text-[13px] mt-2">{item.text}</div>
147+
)}
148+
</div>
149+
))}
150+
151+
<div className="flex items-center gap-2 text-[13px] pt-2">
152+
<span className="text-emerald-400"></span>
153+
<span className="text-sky-400">~/banglascript</span>
154+
<span className="text-green-600">$</span>
155+
<span className="text-gray-300">{currentInput}</span>
156+
<motion.span
157+
className="inline-block w-1 h-[14px] bg-gray-500 ml-0.5"
158+
animate={{ opacity: [1, 0.3, 1] }}
159+
transition={{ duration: 0.8, repeat: Infinity, ease: "linear" }}
160+
/>
161+
</div>
162+
</div>
115163
</div>
116164
);
117165
}

0 commit comments

Comments
 (0)