Tauri 编辑器应用框架
This commit is contained in:
12
packages/editor-app/index.html
Normal file
12
packages/editor-app/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>ECS Framework Editor</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
31
packages/editor-app/package.json
Normal file
31
packages/editor-app/package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@esengine/editor-app",
|
||||
"version": "1.0.0",
|
||||
"description": "ECS Framework Editor Application - Cross-platform desktop editor",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"tauri": "tauri",
|
||||
"tauri:dev": "tauri dev",
|
||||
"tauri:build": "tauri build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@esengine/ecs-framework": "file:../core",
|
||||
"@esengine/editor-core": "file:../editor-core",
|
||||
"@tauri-apps/api": "^2.2.0",
|
||||
"@tauri-apps/plugin-shell": "^2.0.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.2.0",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.0.7"
|
||||
}
|
||||
}
|
||||
29
packages/editor-app/src-tauri/Cargo.toml
Normal file
29
packages/editor-app/src-tauri/Cargo.toml
Normal file
@@ -0,0 +1,29 @@
|
||||
[package]
|
||||
name = "ecs-editor"
|
||||
version = "1.0.0"
|
||||
description = "ECS Framework Editor - Cross-platform desktop editor"
|
||||
authors = ["yhh"]
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "ecs_editor_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2", features = [] }
|
||||
tauri-plugin-shell = "2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
[profile.dev]
|
||||
incremental = true
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = "s"
|
||||
panic = "abort"
|
||||
strip = true
|
||||
3
packages/editor-app/src-tauri/build.rs
Normal file
3
packages/editor-app/src-tauri/build.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
25
packages/editor-app/src-tauri/src/commands.rs
Normal file
25
packages/editor-app/src-tauri/src/commands.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ProjectInfo {
|
||||
pub name: String,
|
||||
pub path: String,
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct EditorConfig {
|
||||
pub theme: String,
|
||||
pub auto_save: bool,
|
||||
pub recent_projects: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for EditorConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
theme: "dark".to_string(),
|
||||
auto_save: true,
|
||||
recent_projects: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
7
packages/editor-app/src-tauri/src/lib.rs
Normal file
7
packages/editor-app/src-tauri/src/lib.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
// ECS Editor Library
|
||||
|
||||
pub mod commands;
|
||||
pub mod project;
|
||||
|
||||
pub use commands::*;
|
||||
pub use project::*;
|
||||
54
packages/editor-app/src-tauri/src/main.rs
Normal file
54
packages/editor-app/src-tauri/src/main.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
// Prevents additional console window on Windows in release
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
use tauri::Manager;
|
||||
|
||||
// IPC Commands
|
||||
#[tauri::command]
|
||||
fn greet(name: &str) -> String {
|
||||
format!("Hello, {}! Welcome to ECS Framework Editor.", name)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn open_project(path: String) -> Result<String, String> {
|
||||
// 项目打开逻辑
|
||||
Ok(format!("Project opened: {}", path))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn save_project(path: String, data: String) -> Result<(), String> {
|
||||
// 项目保存逻辑
|
||||
std::fs::write(&path, data)
|
||||
.map_err(|e| format!("Failed to save project: {}", e))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn export_binary(data: Vec<u8>, output_path: String) -> Result<(), String> {
|
||||
// 二进制导出逻辑
|
||||
std::fs::write(&output_path, data)
|
||||
.map_err(|e| format!("Failed to export binary: {}", e))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.setup(|app| {
|
||||
// 应用启动时的初始化逻辑
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let window = app.get_webview_window("main").unwrap();
|
||||
window.open_devtools();
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
greet,
|
||||
open_project,
|
||||
save_project,
|
||||
export_binary
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
42
packages/editor-app/src-tauri/src/project.rs
Normal file
42
packages/editor-app/src-tauri/src/project.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use std::path::PathBuf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Project {
|
||||
pub name: String,
|
||||
pub path: PathBuf,
|
||||
pub scenes: Vec<String>,
|
||||
pub assets: Vec<String>,
|
||||
}
|
||||
|
||||
impl Project {
|
||||
pub fn new(name: String, path: PathBuf) -> Self {
|
||||
Self {
|
||||
name,
|
||||
path,
|
||||
scenes: Vec::new(),
|
||||
assets: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(path: &PathBuf) -> Result<Self, String> {
|
||||
let content = std::fs::read_to_string(path)
|
||||
.map_err(|e| format!("Failed to read project file: {}", e))?;
|
||||
|
||||
serde_json::from_str(&content)
|
||||
.map_err(|e| format!("Failed to parse project file: {}", e))
|
||||
}
|
||||
|
||||
pub fn save(&self) -> Result<(), String> {
|
||||
let mut project_file = self.path.clone();
|
||||
project_file.push("project.json");
|
||||
|
||||
let content = serde_json::to_string_pretty(self)
|
||||
.map_err(|e| format!("Failed to serialize project: {}", e))?;
|
||||
|
||||
std::fs::write(&project_file, content)
|
||||
.map_err(|e| format!("Failed to write project file: {}", e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
59
packages/editor-app/src-tauri/tauri.conf.json
Normal file
59
packages/editor-app/src-tauri/tauri.conf.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"productName": "ECS Framework Editor",
|
||||
"version": "1.0.0",
|
||||
"identifier": "com.esengine.editor",
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
"devUrl": "http://localhost:5173",
|
||||
"beforeBuildCommand": "npm run build",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": ""
|
||||
},
|
||||
"macOS": {
|
||||
"entitlements": null,
|
||||
"exceptionDomain": "",
|
||||
"frameworks": [],
|
||||
"providerShortName": null,
|
||||
"signingIdentity": null
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "ECS Framework Editor",
|
||||
"width": 1280,
|
||||
"height": 800,
|
||||
"minWidth": 800,
|
||||
"minHeight": 600,
|
||||
"resizable": true,
|
||||
"fullscreen": false,
|
||||
"decorations": true,
|
||||
"transparent": false,
|
||||
"center": true,
|
||||
"skipTaskbar": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
}
|
||||
},
|
||||
"plugins": {
|
||||
"shell": {
|
||||
"open": true
|
||||
}
|
||||
}
|
||||
}
|
||||
89
packages/editor-app/src/App.tsx
Normal file
89
packages/editor-app/src/App.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Core } from '@esengine/ecs-framework';
|
||||
import { EditorPluginManager, UIRegistry, MessageHub, SerializerRegistry } from '@esengine/editor-core';
|
||||
import { SceneInspectorPlugin } from './plugins/SceneInspectorPlugin';
|
||||
import { TauriAPI } from './api/tauri';
|
||||
import './styles/App.css';
|
||||
|
||||
function App() {
|
||||
const [core, setCore] = useState<Core | null>(null);
|
||||
const [pluginManager, setPluginManager] = useState<EditorPluginManager | null>(null);
|
||||
const [status, setStatus] = useState('Initializing...');
|
||||
|
||||
useEffect(() => {
|
||||
const initializeEditor = async () => {
|
||||
try {
|
||||
const coreInstance = Core.create({ debug: true });
|
||||
|
||||
const uiRegistry = new UIRegistry();
|
||||
const messageHub = new MessageHub();
|
||||
const serializerRegistry = new SerializerRegistry();
|
||||
|
||||
Core.services.registerInstance(UIRegistry, uiRegistry);
|
||||
Core.services.registerInstance(MessageHub, messageHub);
|
||||
Core.services.registerInstance(SerializerRegistry, serializerRegistry);
|
||||
|
||||
const pluginMgr = new EditorPluginManager();
|
||||
pluginMgr.initialize(coreInstance, Core.services);
|
||||
|
||||
await pluginMgr.installEditor(new SceneInspectorPlugin());
|
||||
|
||||
const greeting = await TauriAPI.greet('Developer');
|
||||
console.log(greeting);
|
||||
|
||||
setCore(coreInstance);
|
||||
setPluginManager(pluginMgr);
|
||||
setStatus('Editor Ready');
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize editor:', error);
|
||||
setStatus('Initialization Failed');
|
||||
}
|
||||
};
|
||||
|
||||
initializeEditor();
|
||||
|
||||
return () => {
|
||||
Core.destroy();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="editor-container">
|
||||
<div className="editor-header">
|
||||
<h1>ECS Framework Editor</h1>
|
||||
<span className="status">{status}</span>
|
||||
</div>
|
||||
|
||||
<div className="editor-content">
|
||||
<div className="sidebar-left">
|
||||
<h3>Hierarchy</h3>
|
||||
<p>Scene hierarchy will appear here</p>
|
||||
</div>
|
||||
|
||||
<div className="main-content">
|
||||
<div className="viewport">
|
||||
<h3>Viewport</h3>
|
||||
<p>Scene viewport will appear here</p>
|
||||
</div>
|
||||
|
||||
<div className="bottom-panel">
|
||||
<h4>Console</h4>
|
||||
<p>Console output will appear here</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="sidebar-right">
|
||||
<h3>Inspector</h3>
|
||||
<p>Entity inspector will appear here</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="editor-footer">
|
||||
<span>Plugins: {pluginManager?.getAllEditorPlugins().length ?? 0}</span>
|
||||
<span>Core: {core ? 'Active' : 'Inactive'}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
55
packages/editor-app/src/api/tauri.ts
Normal file
55
packages/editor-app/src/api/tauri.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
|
||||
/**
|
||||
* Tauri IPC 通信层
|
||||
*/
|
||||
export class TauriAPI {
|
||||
/**
|
||||
* 打招呼(测试命令)
|
||||
*/
|
||||
static async greet(name: string): Promise<string> {
|
||||
return await invoke<string>('greet', { name });
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开项目
|
||||
*/
|
||||
static async openProject(path: string): Promise<string> {
|
||||
return await invoke<string>('open_project', { path });
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存项目
|
||||
*/
|
||||
static async saveProject(path: string, data: string): Promise<void> {
|
||||
return await invoke<void>('save_project', { path, data });
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出二进制数据
|
||||
*/
|
||||
static async exportBinary(data: Uint8Array, outputPath: string): Promise<void> {
|
||||
return await invoke<void>('export_binary', {
|
||||
data: Array.from(data),
|
||||
outputPath
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目信息
|
||||
*/
|
||||
export interface ProjectInfo {
|
||||
name: string;
|
||||
path: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑器配置
|
||||
*/
|
||||
export interface EditorConfig {
|
||||
theme: string;
|
||||
autoSave: boolean;
|
||||
recentProjects: string[];
|
||||
}
|
||||
10
packages/editor-app/src/main.tsx
Normal file
10
packages/editor-app/src/main.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
import './styles/index.css';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
130
packages/editor-app/src/plugins/SceneInspectorPlugin.ts
Normal file
130
packages/editor-app/src/plugins/SceneInspectorPlugin.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import type { Core, ServiceContainer } from '@esengine/ecs-framework';
|
||||
import { IEditorPlugin, EditorPluginCategory, PanelPosition } from '@esengine/editor-core';
|
||||
import type { MenuItem, ToolbarItem, PanelDescriptor, ISerializer } from '@esengine/editor-core';
|
||||
|
||||
/**
|
||||
* Scene Inspector 插件
|
||||
*
|
||||
* 提供场景层级视图和实体检视功能
|
||||
*/
|
||||
export class SceneInspectorPlugin implements IEditorPlugin {
|
||||
readonly name = '@esengine/scene-inspector';
|
||||
readonly version = '1.0.0';
|
||||
readonly displayName = 'Scene Inspector';
|
||||
readonly category = EditorPluginCategory.Inspector;
|
||||
readonly description = 'Scene hierarchy and entity inspector';
|
||||
readonly icon = '🔍';
|
||||
|
||||
async install(_core: Core, _services: ServiceContainer): Promise<void> {
|
||||
console.log('[SceneInspectorPlugin] Installed');
|
||||
}
|
||||
|
||||
async uninstall(): Promise<void> {
|
||||
console.log('[SceneInspectorPlugin] Uninstalled');
|
||||
}
|
||||
|
||||
registerMenuItems(): MenuItem[] {
|
||||
return [
|
||||
{
|
||||
id: 'view-scene-inspector',
|
||||
label: 'Scene Inspector',
|
||||
parentId: 'view',
|
||||
onClick: () => {
|
||||
console.log('Toggle Scene Inspector');
|
||||
},
|
||||
shortcut: 'Ctrl+Shift+I',
|
||||
order: 100
|
||||
},
|
||||
{
|
||||
id: 'scene-create-entity',
|
||||
label: 'Create Entity',
|
||||
parentId: 'scene',
|
||||
onClick: () => {
|
||||
console.log('Create new entity');
|
||||
},
|
||||
shortcut: 'Ctrl+N',
|
||||
order: 10
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
registerToolbar(): ToolbarItem[] {
|
||||
return [
|
||||
{
|
||||
id: 'toolbar-create-entity',
|
||||
label: 'New Entity',
|
||||
groupId: 'entity-tools',
|
||||
icon: '➕',
|
||||
onClick: () => {
|
||||
console.log('Create entity from toolbar');
|
||||
},
|
||||
order: 10
|
||||
},
|
||||
{
|
||||
id: 'toolbar-delete-entity',
|
||||
label: 'Delete Entity',
|
||||
groupId: 'entity-tools',
|
||||
icon: '🗑️',
|
||||
onClick: () => {
|
||||
console.log('Delete entity from toolbar');
|
||||
},
|
||||
order: 20
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
registerPanels(): PanelDescriptor[] {
|
||||
return [
|
||||
{
|
||||
id: 'panel-scene-hierarchy',
|
||||
title: 'Scene Hierarchy',
|
||||
position: PanelPosition.Left,
|
||||
defaultSize: 250,
|
||||
resizable: true,
|
||||
closable: false,
|
||||
icon: '📋',
|
||||
order: 10
|
||||
},
|
||||
{
|
||||
id: 'panel-entity-inspector',
|
||||
title: 'Entity Inspector',
|
||||
position: PanelPosition.Right,
|
||||
defaultSize: 300,
|
||||
resizable: true,
|
||||
closable: false,
|
||||
icon: '🔎',
|
||||
order: 10
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
getSerializers(): ISerializer[] {
|
||||
return [
|
||||
{
|
||||
serialize: (data: any) => {
|
||||
const json = JSON.stringify(data);
|
||||
const encoder = new TextEncoder();
|
||||
return encoder.encode(json);
|
||||
},
|
||||
deserialize: (data: Uint8Array) => {
|
||||
const decoder = new TextDecoder();
|
||||
const json = decoder.decode(data);
|
||||
return JSON.parse(json);
|
||||
},
|
||||
getSupportedType: () => 'scene'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
async onEditorReady(): Promise<void> {
|
||||
console.log('[SceneInspectorPlugin] Editor is ready');
|
||||
}
|
||||
|
||||
async onProjectOpen(projectPath: string): Promise<void> {
|
||||
console.log(`[SceneInspectorPlugin] Project opened: ${projectPath}`);
|
||||
}
|
||||
|
||||
async onProjectClose(): Promise<void> {
|
||||
console.log('[SceneInspectorPlugin] Project closed');
|
||||
}
|
||||
}
|
||||
99
packages/editor-app/src/styles/App.css
Normal file
99
packages/editor-app/src/styles/App.css
Normal file
@@ -0,0 +1,99 @@
|
||||
.editor-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #1e1e1e;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.editor-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 16px;
|
||||
background-color: #2d2d2d;
|
||||
border-bottom: 1px solid #3e3e3e;
|
||||
}
|
||||
|
||||
.editor-header h1 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.editor-header .status {
|
||||
font-size: 12px;
|
||||
color: #4ec9b0;
|
||||
}
|
||||
|
||||
.editor-content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar-left,
|
||||
.sidebar-right {
|
||||
width: 250px;
|
||||
background-color: #252526;
|
||||
border-right: 1px solid #3e3e3e;
|
||||
padding: 12px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar-right {
|
||||
border-right: none;
|
||||
border-left: 1px solid #3e3e3e;
|
||||
}
|
||||
|
||||
.sidebar-left h3,
|
||||
.sidebar-right h3 {
|
||||
font-size: 14px;
|
||||
margin-bottom: 12px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.viewport {
|
||||
flex: 1;
|
||||
background-color: #1e1e1e;
|
||||
border-bottom: 1px solid #3e3e3e;
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.viewport h3 {
|
||||
font-size: 14px;
|
||||
margin-bottom: 12px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.bottom-panel {
|
||||
height: 200px;
|
||||
background-color: #252526;
|
||||
padding: 12px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.bottom-panel h4 {
|
||||
font-size: 12px;
|
||||
margin-bottom: 8px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.editor-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 4px 16px;
|
||||
background-color: #007acc;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
}
|
||||
19
packages/editor-app/src/styles/index.css
Normal file
19
packages/editor-app/src/styles/index.css
Normal file
@@ -0,0 +1,19 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#root {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
23
packages/editor-app/tsconfig.json
Normal file
23
packages/editor-app/tsconfig.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
27
packages/editor-app/vite.config.ts
Normal file
27
packages/editor-app/vite.config.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
const host = process.env.TAURI_DEV_HOST;
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
clearScreen: false,
|
||||
server: {
|
||||
host: host || false,
|
||||
port: 5173,
|
||||
strictPort: true,
|
||||
hmr: host
|
||||
? {
|
||||
protocol: 'ws',
|
||||
host,
|
||||
port: 5183,
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
envPrefix: ['VITE_', 'TAURI_'],
|
||||
build: {
|
||||
target: 'es2021',
|
||||
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
|
||||
sourcemap: !!process.env.TAURI_DEBUG,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user