diff --git a/apps/executeJS/src/app/index.tsx b/apps/executeJS/src/app/index.tsx index 3c3a5f7..4be21c8 100644 --- a/apps/executeJS/src/app/index.tsx +++ b/apps/executeJS/src/app/index.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { Providers } from './providers'; -import { EditorPage } from '../pages/editor'; +import { PlaygroundGroups } from '../pages/playground'; export const App: React.FC = () => { return ( - + ); }; diff --git a/apps/executeJS/src/pages/editor/index.ts b/apps/executeJS/src/pages/editor/index.ts deleted file mode 100644 index 0601973..0000000 --- a/apps/executeJS/src/pages/editor/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './editor-page'; diff --git a/apps/executeJS/src/pages/playground/index.ts b/apps/executeJS/src/pages/playground/index.ts new file mode 100644 index 0000000..e9d1de9 --- /dev/null +++ b/apps/executeJS/src/pages/playground/index.ts @@ -0,0 +1,2 @@ +export * from './playground-page'; +export * from './playground-groups'; diff --git a/apps/executeJS/src/pages/playground/playground-groups.tsx b/apps/executeJS/src/pages/playground/playground-groups.tsx new file mode 100644 index 0000000..27d01df --- /dev/null +++ b/apps/executeJS/src/pages/playground/playground-groups.tsx @@ -0,0 +1,90 @@ +import { useState } from 'react'; +import { PlaygroundPage } from './playground-page'; +import { Cross2Icon, PlusIcon } from '@radix-ui/react-icons'; + +interface Tab { + id: string; + title: string; +} + +const INITIAL_TAB_TITLE = '✨New Playground'; + +const initialTabs: Tab[] = [{ id: 'playground-1', title: INITIAL_TAB_TITLE }]; + +export const PlaygroundGroups: React.FC = () => { + const [tabs, setTabs] = useState(initialTabs); + + const handleCloseTab = (tabId: string) => { + setTabs((prevTabs) => { + if (prevTabs.length === 1) { + return prevTabs; // 최소 하나의 탭은 유지 + } + + return prevTabs.filter((tab) => tab.id !== tabId); + }); + }; + + const handleAddTab = () => { + setTabs((prevTabs) => { + const date = new Date().valueOf(); + const newTabId = `playground-${date}`; + const newTab: Tab = { + id: newTabId, + title: INITIAL_TAB_TITLE, + }; + + return [...prevTabs, newTab]; + }); + }; + + return ( +
+
+
+ {tabs.map(({ id, title }) => { + return ( +
+ {/* TODO: 탭 최대 너비에 따른 제목 ellipsis 처리 @bori */} + + +
+ ); + })} +
+ + +
+ + {/* TODO: 활성화된 탭에 따른 플레이그라운드 렌더링 @bori */} + +
+ ); +}; diff --git a/apps/executeJS/src/pages/editor/editor-page.test.tsx b/apps/executeJS/src/pages/playground/playground-page.test.tsx similarity index 79% rename from apps/executeJS/src/pages/editor/editor-page.test.tsx rename to apps/executeJS/src/pages/playground/playground-page.test.tsx index d5692e9..f0641e8 100644 --- a/apps/executeJS/src/pages/editor/editor-page.test.tsx +++ b/apps/executeJS/src/pages/playground/playground-page.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react'; import { describe, it, expect, vi } from 'vitest'; import '@testing-library/jest-dom'; -import { EditorPage } from './editor-page'; +import { PlaygroundPage } from './playground-page'; // Tauri API 모킹 vi.mock('@tauri-apps/api/core', () => ({ @@ -13,9 +13,9 @@ vi.mock('@legendapp/state/react', () => ({ useObservable: vi.fn(() => []), })); -describe('EditorPage', () => { +describe('PlaygroundPage', () => { it('renders without crashing', () => { - render(); + render(); expect(screen.getByText(/실행 \(Cmd\+Enter\)/)).toBeInTheDocument(); }); }); diff --git a/apps/executeJS/src/pages/editor/editor-page.tsx b/apps/executeJS/src/pages/playground/playground-page.tsx similarity index 98% rename from apps/executeJS/src/pages/editor/editor-page.tsx rename to apps/executeJS/src/pages/playground/playground-page.tsx index 1f9bab6..11962a0 100644 --- a/apps/executeJS/src/pages/editor/editor-page.tsx +++ b/apps/executeJS/src/pages/playground/playground-page.tsx @@ -5,7 +5,7 @@ import { OutputPanel } from '@/widgets/output-panel'; import { useExecutionStore } from '@/features/execute-code'; import { PlayIcon, StopIcon } from '@radix-ui/react-icons'; -export const EditorPage: React.FC = () => { +export const PlaygroundPage: React.FC = () => { const [code, setCode] = useState('console.log("Hello, ExecuteJS!");'); const { result: executionResult, diff --git a/docs/docs/guide/development.mdx b/docs/docs/guide/development.mdx index 1cfe188..00fa53a 100644 --- a/docs/docs/guide/development.mdx +++ b/docs/docs/guide/development.mdx @@ -122,8 +122,8 @@ src/ │ ├── index.tsx # 앱 루트 컴포넌트 │ └── providers.tsx # 전역 프로바이더 (Legend State, Radix UI) ├── pages/ # 페이지 레벨 컴포넌트 -│ └── editor/ -│ └── EditorPage.tsx # 메인 에디터 페이지 +│ └── playground/ +│ └── PlaygroundPage.tsx # 플레이그라운드 페이지 ├── widgets/ # 복합 UI 블록 │ ├── code-editor/ │ │ └── CodeEditor.tsx # Monaco Editor 래퍼