p-doom/crowd-code-dataset-0.2 huggingface dataset:
[tab] src/CodeEditor.tsx (typescriptreact)
'use client'
import React, { ReactElement, useEffect, useRef, useState } from 'react'
import { Editor, Monaco } from '@monaco-editor/react'
import { emmetCSS, emmetHTML, emmetJSX } from 'emmet-monaco-es'
import { editor } from 'monaco-editor'
import { SiCss3, SiHtml5, SiJavascript, SiTypescript } from 'react-icons/si'

export interface MonacoFile {
	name: string
	language: string
	value: string
	isChanged?: boolean
}
export interface CodeEditorFilesMap {
	[key: string]: MonacoFile
}

interface CodeEditorProps {
	currenFile: string
	files: CodeEditorFilesMap
	externalEditorRef?: React.MutableRefObject<editor.IStandaloneCodeEditor>
	externalSelectedFile?: React.MutableRefObject<string>
}

const fileIcons: { [key: string]: ReactElement } = {
	'html': <SiHtml5 />,
	'css': <SiCss3 />,
	'js': <SiJavascript />,
	'ts': <SiTypescript />,
}

export default function CodeEditor({
	files,
	currenFile,
	externalEditorRef,
	externalSelectedFile,
}: CodeEditorProps) {
	const [fileName, setFileName] = useState(currenFile)
	// const prevFileName = useRef(currenFile)
	const localEditorRef = useRef(null as unknown as editor.IStandaloneCodeEditor)
	const editorRef = externalEditorRef !== undefined ? externalEditorRef : localEditorRef
	const monacoRef = useRef(null as unknown as Monaco)

	const file = files ? files[fileName] : null

	useEffect(() => {
		setFileName(currenFile)
		if (externalSelectedFile !== undefined) externalSelectedFile.current = currenFile
	}, [currenFile, externalSelectedFile])

	const handleTabChange = (tabFile: string) => {
		setFileName(tabFile)
		if (!files) return
		const file = files[tabFile]
		editorRef.current?.setValue(file?.value)
		if (externalSelectedFile !== undefined) externalSelectedFile.current = tabFile
		console.log('externalSelectedFile', externalSelectedFile?.current)
	}

	//add emmet support
	const handleEditorDidMount = (editor: editor.IStandaloneCodeEditor, monaco: Monaco) => {
		emmetHTML(monaco)
		emmetCSS(monaco)
		emmetJSX(monaco)
		editorRef.current = editor
		monacoRef.current = monaco
	}

	return (
		<div className='w-full'>
			<div className=' h-[50vh] w-full'>
				{files && (
					<div>
						{Object.entries(files).map(tabFile => (
							<button
								key={tabFile[0]}
								onClick={() => handleTabChange(tabFile[0])}
								className={`inline-flex gap-1 items-center p-2 border-t-3 mr-[0.15rem] hover:bg-[#2e2e2e] text-neutral-200 text-left ${
									fileName === tabFile[0]
										? 'bg-[#1e1e1e] border-t-[#3399cc]'
										: 'bg-[#34352f] border-t-[#34352f]'
								} `}
							>
								{fileIcons[files[tabFile[0]].language]}
								{tabFile[1].name}
							</button>
						))}
						{/* <button onClick={() => handleEditorChange('hello')}>Add Change</button> */}
					</div>
				)}
				<Editor
					height='calc(100% - 40px)'
					width='100%'
					language={file?.language ? file.language : 'auto'}
					path={currenFile}
					theme='vs-dark'
					onMount={handleEditorDidMount}
					options={{
						readOnly: true,
					}}
				/>
			</div>
		</div>
	)
}
[tab] src/main.tsx (typescriptreact)
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import './index.css'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
[tab] src/App.tsx (typescriptreact)
import PlayerProvider from "./PlayerProvider";
import StoreProvider from "./redux/StoreProvider";

function App() {
	return (
		<StoreProvider>
			<div className="min-h-screen bg-gradient-to-br from-stone-900 to-stone-800 text-white p-8">
				<div className="max-w-6xl mx-auto">
					<h1 className="text-5xl font-bold text-center mb-8 bg-clip-text text-transparent bg-gradient-to-r from-yellow-400 to-orange-500">
						VS Code Recorder Player
					</h1>
					<div className="bg-stone-800/50 backdrop-blur-sm rounded-xl shadow-xl p-6">
						<PlayerProvider />
					</div>
				</div>
			</div>
		</StoreProvider>
	);
}

export default App;
[tab] src/redux/StoreProvider.tsx (typescriptreact)
import { Provider } from 'react-redux'

import { store } from './store'

export default function StoreProvider({ children }: { children: React.ReactNode }) {
	return <Provider store={store}>{children}</Provider>
}
[tab] vite.config.ts (typescript)
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'

// https://vitejs.dev/config/
export default defineConfig({
	plugins: [react()],
	server: {
		open: true, // This will open the browser automatically
	},
})
[tab] index.html (html)
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React + TS</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
[tab] src/PlayerProvider.tsx (typescriptreact)
import CodePlayer from "./CodePlayer";
import FileSelector from "./FileSelector";
import Player from "./Player";
import { useAppSelector } from "./redux/store";

function PlayerProvider() {
	const content = useAppSelector((state) => state.player.content);
	return (
		<div className="space-y-6">
			<div className="bg-gray-700/30 rounded-lg p-4">
				<FileSelector />
			</div>

			{!!content.length && (
				<div className="space-y-4">
					<div className="bg-gray-700/30 rounded-lg p-4">
						<CodePlayer />

						<Player />
					</div>
				</div>
			)}
		</div>
	);
}

export default PlayerProvider;