Complete main UI #37

Merged
FatttSnake merged 192 commits from FatttSnake into dev 2024-02-23 16:31:17 +08:00
8 changed files with 33 additions and 47 deletions
Showing only changes of commit dc4e49343b - Show all commits

View File

@@ -1,14 +1,10 @@
import React from 'react' import React from 'react'
import '@/components/Playground/CodeEditor/FileSelector/file-selector.scss' import '@/components/Playground/CodeEditor/FileSelector/file-selector.scss'
import { IFiles } from '@/components/Playground/shared'
import {
ENTRY_FILE_NAME,
getFileNameList,
IMPORT_MAP_FILE_NAME
} from '@/components/Playground/files'
import Item from '@/components/Playground/CodeEditor/FileSelector/Item'
import HideScrollbar, { HideScrollbarElement } from '@/components/common/HideScrollbar' import HideScrollbar, { HideScrollbarElement } from '@/components/common/HideScrollbar'
import FlexBox from '@/components/common/FlexBox' import FlexBox from '@/components/common/FlexBox'
import { IFiles } from '@/components/Playground/shared'
import { getFileNameList, IMPORT_MAP_FILE_NAME } from '@/components/Playground/files'
import Item from '@/components/Playground/CodeEditor/FileSelector/Item'
interface FileSelectorProps { interface FileSelectorProps {
files?: IFiles files?: IFiles
@@ -103,10 +99,8 @@ const FileSelector: React.FC<FileSelectorProps> = ({
} }
const handleOnValidateTab = (newFileName: string, oldFileName: string) => { const handleOnValidateTab = (newFileName: string, oldFileName: string) => {
if (!/\.(jsx|tsx|js|ts|css|json|svg)$/.test(newFileName)) { if (!/\.(jsx|tsx|js|ts|css|json)$/.test(newFileName)) {
onError?.( onError?.('Playground only supports *.jsx, *.tsx, *.js, *.ts, *.css, *.json files.')
'Playground only supports *.jsx, *.tsx, *.js, *.ts, *.css, *.json, *.svg files.'
)
return false return false
} }
@@ -128,8 +122,7 @@ const FileSelector: React.FC<FileSelectorProps> = ({
onRemoveFile?.(fileName) onRemoveFile?.(fileName)
if (fileName === selectedFileName) { if (fileName === selectedFileName) {
const keys = getFileNameList(files).filter( const keys = getFileNameList(files).filter(
(item) => (item) => ![IMPORT_MAP_FILE_NAME].includes(item) && !files[item].hidden
![IMPORT_MAP_FILE_NAME, ENTRY_FILE_NAME].includes(item) && !files[item].hidden
) )
const index = keys.indexOf(fileName) - 1 const index = keys.indexOf(fileName) - 1
if (index >= 0) { if (index >= 0) {
@@ -144,9 +137,7 @@ const FileSelector: React.FC<FileSelectorProps> = ({
getFileNameList(files).length getFileNameList(files).length
? setTabs( ? setTabs(
getFileNameList(files).filter( getFileNameList(files).filter(
(item) => (item) => ![IMPORT_MAP_FILE_NAME].includes(item) && !files[item].hidden
![IMPORT_MAP_FILE_NAME, ENTRY_FILE_NAME].includes(item) &&
!files[item].hidden
) )
) )
: setTabs([]) : setTabs([])

View File

@@ -1,6 +1,7 @@
import React from 'react' import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import '@/components/Playground/CodeEditor/code-editor.scss' import '@/components/Playground/CodeEditor/code-editor.scss'
import FlexBox from '@/components/common/FlexBox'
import { IEditorOptions, IFiles, ITheme } from '@/components/Playground/shared' import { IEditorOptions, IFiles, ITheme } from '@/components/Playground/shared'
import { import {
fileNameToLanguage, fileNameToLanguage,
@@ -9,7 +10,6 @@ import {
} from '@/components/Playground/files' } from '@/components/Playground/files'
import FileSelector from '@/components/Playground/CodeEditor/FileSelector' import FileSelector from '@/components/Playground/CodeEditor/FileSelector'
import Editor from '@/components/Playground/CodeEditor/Editor' import Editor from '@/components/Playground/CodeEditor/Editor'
import FlexBox from '@/components/common/FlexBox'
interface CodeEditorProps { interface CodeEditorProps {
theme?: ITheme theme?: ITheme

View File

@@ -1,9 +1,9 @@
import React, { useRef, useState } from 'react' import React, { useRef, useState } from 'react'
import { IFiles, IImportMap } from '@/components/Playground/shared'
import iframeRaw from '@/components/Playground/Output/Preview/iframe.html?raw'
import { useUpdatedEffect } from '@/util/hooks' import { useUpdatedEffect } from '@/util/hooks'
import Compiler from '@/components/Playground/compiler'
import '@/components/Playground/Output/Preview/preview.scss' import '@/components/Playground/Output/Preview/preview.scss'
import { IFiles, IImportMap } from '@/components/Playground/shared'
import Compiler from '@/components/Playground/compiler'
import iframeRaw from '@/components/Playground/Output/Preview/iframe.html?raw'
interface PreviewProps { interface PreviewProps {
iframeKey: string iframeKey: string

View File

@@ -1,13 +1,13 @@
import React, { useState } from 'react' import React from 'react'
import MonacoEditor from '@monaco-editor/react' import MonacoEditor from '@monaco-editor/react'
import { Loader } from 'esbuild-wasm' import { Loader } from 'esbuild-wasm'
import '@/components/Playground/Output/Transform/transform.scss' import '@/components/Playground/Output/Transform/transform.scss'
import { useUpdatedEffect } from '@/util/hooks.tsx' import { useUpdatedEffect } from '@/util/hooks'
import { IFile, ITheme } from '@/components/Playground/shared.ts' import { IFile, ITheme } from '@/components/Playground/shared'
import Compiler from '@/components/Playground/compiler.ts' import { addReactImport } from '@/components/Playground/utils'
import { cssToJs, jsonToJs } from '@/components/Playground/files.ts' import { cssToJs, jsonToJs } from '@/components/Playground/files'
import { MonacoEditorConfig } from '@/components/Playground/CodeEditor/Editor/monacoConfig.ts' import Compiler from '@/components/Playground/compiler'
import { addReactImport } from '@/components/Playground/utils.ts' import { MonacoEditorConfig } from '@/components/Playground/CodeEditor/Editor/monacoConfig'
interface OutputProps { interface OutputProps {
file: IFile file: IFile

View File

@@ -1,8 +1,8 @@
import React, { useState } from 'react' import React from 'react'
import FlexBox from '@/components/common/FlexBox.tsx' import FlexBox from '@/components/common/FlexBox'
import { IFiles, IImportMap } from '@/components/Playground/shared'
import FileSelector from '@/components/Playground/CodeEditor/FileSelector' import FileSelector from '@/components/Playground/CodeEditor/FileSelector'
import Transform from '@/components/Playground/Output/Transform' import Transform from '@/components/Playground/Output/Transform'
import { IFiles, IImportMap } from '@/components/Playground/shared.ts'
import Preview from '@/components/Playground/Output/Preview' import Preview from '@/components/Playground/Output/Preview'
interface OutputProps { interface OutputProps {

View File

@@ -1,9 +1,9 @@
import esbuild, { Loader, OnLoadArgs, Plugin, PluginBuild } from 'esbuild-wasm' import esbuild, { Loader, OnLoadArgs, Plugin, PluginBuild } from 'esbuild-wasm'
import { IFiles, IImportMap } from '@/components/Playground/shared.ts'
import { cssToJs, ENTRY_FILE_NAME, jsonToJs } from '@/components/Playground/files.ts'
import localforage from 'localforage' import localforage from 'localforage'
import axios from 'axios' import axios from 'axios'
import { addReactImport } from '@/components/Playground/utils.ts' import { IFiles, IImportMap } from '@/components/Playground/shared'
import { cssToJs, ENTRY_FILE_NAME, jsonToJs } from '@/components/Playground/files'
import { addReactImport } from '@/components/Playground/utils'
class Compiler { class Compiler {
private init = false private init = false
@@ -108,6 +108,9 @@ class Compiler {
path: `${args.path.substring(2)}.js` path: `${args.path.substring(2)}.js`
} }
} }
if (/\.\/.*\.css/.test(args.path) && !args.resolveDir) {
throw Error(`Css '${args.path}' not found`)
}
if (/^https?:\/\/.*/.test(args.path)) { if (/^https?:\/\/.*/.test(args.path)) {
return { return {
@@ -155,14 +158,6 @@ class Compiler {
} }
}) })
build.onLoad({ filter: /.*\.svg$/ }, async (args: OnLoadArgs) => {
const contents = files[args.path].value
return {
loader: 'text',
contents
}
})
build.onLoad({ filter: /.*/ }, async (args: OnLoadArgs) => { build.onLoad({ filter: /.*/ }, async (args: OnLoadArgs) => {
if (args.path === ENTRY_FILE_NAME) { if (args.path === ENTRY_FILE_NAME) {
return { return {

View File

@@ -1,9 +1,9 @@
import { strFromU8, strToU8, unzlibSync, zlibSync } from 'fflate' import { strFromU8, strToU8, unzlibSync, zlibSync } from 'fflate'
import { IFile, IFiles, IImportMap, ILanguage } from '@/components/Playground/shared'
import importMap from '@/components/Playground/template/import-map.json?raw' import importMap from '@/components/Playground/template/import-map.json?raw'
import AppCss from '@/components/Playground/template/src/App.css?raw' import AppCss from '@/components/Playground/template/src/App.css?raw'
import App from '@/components/Playground/template/src/App.tsx?raw' import App from '@/components/Playground/template/src/App.tsx?raw'
import main from '@/components/Playground/template/src/main.tsx?raw' import main from '@/components/Playground/template/src/main.tsx?raw'
import { IFile, IFiles, IImportMap, ILanguage } from '@/components/Playground/shared'
export const MAIN_FILE_NAME = 'App.tsx' export const MAIN_FILE_NAME = 'App.tsx'
export const IMPORT_MAP_FILE_NAME = 'import-map.json' export const IMPORT_MAP_FILE_NAME = 'import-map.json'
@@ -17,7 +17,6 @@ export const fileNameToLanguage = (name: string): ILanguage => {
if (['ts', 'tsx'].includes(suffix)) return 'typescript' if (['ts', 'tsx'].includes(suffix)) return 'typescript'
if (['json'].includes(suffix)) return 'json' if (['json'].includes(suffix)) return 'json'
if (['css'].includes(suffix)) return 'css' if (['css'].includes(suffix)) return 'css'
if (['svg'].includes(suffix)) return 'xml'
return 'javascript' return 'javascript'
} }
@@ -95,7 +94,8 @@ export const initFiles: IFiles = getFilesFromUrl() || {
[ENTRY_FILE_NAME]: { [ENTRY_FILE_NAME]: {
name: ENTRY_FILE_NAME, name: ENTRY_FILE_NAME,
language: fileNameToLanguage(ENTRY_FILE_NAME), language: fileNameToLanguage(ENTRY_FILE_NAME),
value: main value: main,
hidden: true
}, },
[MAIN_FILE_NAME]: { [MAIN_FILE_NAME]: {
name: MAIN_FILE_NAME, name: MAIN_FILE_NAME,

View File

@@ -1,10 +1,10 @@
import React, { useState } from 'react' import React from 'react'
import '@/components/Playground/playground.scss' import '@/components/Playground/playground.scss'
import { IFiles, IImportMap } from '@/components/Playground/shared'
import { IMPORT_MAP_FILE_NAME, MAIN_FILE_NAME } from '@/components/Playground/files'
import FlexBox from '@/components/common/FlexBox' import FlexBox from '@/components/common/FlexBox'
import CodeEditor from '@/components/Playground/CodeEditor' import CodeEditor from '@/components/Playground/CodeEditor'
import Output from '@/components/Playground/Output' import Output from '@/components/Playground/Output'
import { IFiles, IImportMap } from '@/components/Playground/shared.ts'
import { IMPORT_MAP_FILE_NAME, MAIN_FILE_NAME } from '@/components/Playground/files.ts'
interface PlaygroundProps { interface PlaygroundProps {
initFiles: IFiles initFiles: IFiles