plusui-native 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +162 -0
  2. package/package.json +36 -0
  3. package/src/assets/icon-generator.js +251 -0
  4. package/src/assets/resource-embedder.js +351 -0
  5. package/src/doctor/detectors/cmake.js +84 -0
  6. package/src/doctor/detectors/compiler.js +145 -0
  7. package/src/doctor/detectors/just.js +45 -0
  8. package/src/doctor/detectors/nodejs.js +57 -0
  9. package/src/doctor/detectors/webview2.js +66 -0
  10. package/src/doctor/index.js +184 -0
  11. package/src/doctor/installers/linux.js +121 -0
  12. package/src/doctor/installers/macos.js +123 -0
  13. package/src/doctor/installers/windows.js +117 -0
  14. package/src/doctor/reporter.js +219 -0
  15. package/src/index.js +904 -0
  16. package/templates/base/Justfile +115 -0
  17. package/templates/base/README.md.template +168 -0
  18. package/templates/base/assets/README.md +88 -0
  19. package/templates/base/assets/icon.png +0 -0
  20. package/templates/manager.js +217 -0
  21. package/templates/react/.vscode/c_cpp_properties.json +24 -0
  22. package/templates/react/CMakeLists.txt.template +151 -0
  23. package/templates/react/frontend/index.html +12 -0
  24. package/templates/react/frontend/package.json.template +24 -0
  25. package/templates/react/frontend/src/App.tsx +134 -0
  26. package/templates/react/frontend/src/main.tsx +10 -0
  27. package/templates/react/frontend/src/styles/app.css +140 -0
  28. package/templates/react/frontend/tsconfig.json +21 -0
  29. package/templates/react/frontend/tsconfig.node.json +11 -0
  30. package/templates/react/frontend/vite.config.ts +14 -0
  31. package/templates/react/main.cpp.template +201 -0
  32. package/templates/react/package.json.template +23 -0
  33. package/templates/solid/.vscode/c_cpp_properties.json +24 -0
  34. package/templates/solid/CMakeLists.txt.template +151 -0
  35. package/templates/solid/frontend/index.html +12 -0
  36. package/templates/solid/frontend/package.json.template +21 -0
  37. package/templates/solid/frontend/src/App.tsx +133 -0
  38. package/templates/solid/frontend/src/main.tsx +5 -0
  39. package/templates/solid/frontend/src/styles/app.css +140 -0
  40. package/templates/solid/frontend/tsconfig.json +22 -0
  41. package/templates/solid/frontend/tsconfig.node.json +11 -0
  42. package/templates/solid/frontend/vite.config.ts +14 -0
  43. package/templates/solid/main.cpp.template +192 -0
  44. package/templates/solid/package.json.template +23 -0
@@ -0,0 +1,151 @@
1
+ cmake_minimum_required(VERSION 3.16)
2
+ project({{PROJECT_NAME}} VERSION {{PROJECT_VERSION}} LANGUAGES CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 20)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
7
+
8
+ # Platform detection
9
+ if(WIN32)
10
+ add_definitions(-DPLUSUI_EDGE)
11
+ elseif(APPLE)
12
+ add_definitions(-DPLUSUI_COCOA)
13
+ else()
14
+ add_definitions(-DPLUSUI_GTK)
15
+ endif()
16
+
17
+ # Development mode flag
18
+ option(PLUSUI_DEV_MODE "Enable development mode (connect to Vite dev server)" OFF)
19
+ if(PLUSUI_DEV_MODE)
20
+ add_definitions(-DPLUSUI_DEV_MODE)
21
+ endif()
22
+
23
+ # Find PlusUI Core library
24
+ # Strategy: Check multiple locations for the Core library
25
+ set(PLUSUI_FOUND FALSE)
26
+
27
+ # Location 1: Local development (sibling to project inside PlusUI repo)
28
+ set(PLUSUI_CORE_DEV "${CMAKE_SOURCE_DIR}/../Core")
29
+ if(EXISTS "${PLUSUI_CORE_DEV}/CMakeLists.txt")
30
+ message(STATUS "Found PlusUI Core at: ${PLUSUI_CORE_DEV}")
31
+ add_subdirectory("${PLUSUI_CORE_DEV}" "${CMAKE_BINARY_DIR}/plusui-core")
32
+ set(PLUSUI_FOUND TRUE)
33
+ endif()
34
+
35
+ # Location 2: Installed via npm (node_modules)
36
+ if(NOT PLUSUI_FOUND)
37
+ set(PLUSUI_CORE_NPM "${CMAKE_SOURCE_DIR}/node_modules/plusui-native-core/Core")
38
+ if(EXISTS "${PLUSUI_CORE_NPM}/CMakeLists.txt")
39
+ message(STATUS "Found PlusUI Core in node_modules: ${PLUSUI_CORE_NPM}")
40
+ add_subdirectory("${PLUSUI_CORE_NPM}" "${CMAKE_BINARY_DIR}/plusui-core")
41
+ set(PLUSUI_FOUND TRUE)
42
+ endif()
43
+ endif()
44
+
45
+ # Location 3: Parent directory development structure
46
+ if(NOT PLUSUI_FOUND)
47
+ set(PLUSUI_CORE_PARENT "${CMAKE_SOURCE_DIR}/../../Core")
48
+ if(EXISTS "${PLUSUI_CORE_PARENT}/CMakeLists.txt")
49
+ message(STATUS "Found PlusUI Core at: ${PLUSUI_CORE_PARENT}")
50
+ add_subdirectory("${PLUSUI_CORE_PARENT}" "${CMAKE_BINARY_DIR}/plusui-core")
51
+ set(PLUSUI_FOUND TRUE)
52
+ endif()
53
+ endif()
54
+
55
+ if(NOT PLUSUI_FOUND)
56
+ message(FATAL_ERROR "
57
+ PlusUI Core not found!
58
+
59
+ Make sure you have run 'npm install' or that this project is inside the PlusUI repository.
60
+
61
+ Searched locations:
62
+ - ${PLUSUI_CORE_DEV}
63
+ - ${PLUSUI_CORE_NPM}
64
+ - ${PLUSUI_CORE_PARENT}
65
+ ")
66
+ endif()
67
+
68
+ # Create the executable
69
+ add_executable({{PROJECT_NAME}} main.cpp)
70
+
71
+ # Optional: Add your own C++ files here
72
+ # file(GLOB_RECURSE MY_SOURCES "features/*.cpp")
73
+ # target_sources({{PROJECT_NAME}} PRIVATE ${MY_SOURCES})
74
+
75
+ # Link PlusUI library
76
+ target_link_libraries({{PROJECT_NAME}} PRIVATE plusui)
77
+ target_include_directories({{PROJECT_NAME}} PRIVATE ${CMAKE_SOURCE_DIR})
78
+
79
+ # Platform-specific setup
80
+ if(WIN32)
81
+ # Windows: WebView2
82
+ # Try to find WebView2 SDK headers
83
+ find_path(WEBVIEW2_INCLUDE_DIR
84
+ NAMES webview2.h
85
+ PATHS
86
+ "${CMAKE_SOURCE_DIR}/packages/Microsoft.Web.WebView2/build/native/include"
87
+ "${CMAKE_BINARY_DIR}/packages/Microsoft.Web.WebView2/build/native/include"
88
+ "$ENV{USERPROFILE}/.nuget/packages/microsoft.web.webview2/1.0.2903.40/build/native/include"
89
+ "$ENV{NUGET_PACKAGES}/microsoft.web.webview2/1.0.2903.40/build/native/include"
90
+ "C:/Program Files (x86)/Microsoft EdgeWebView/runtimes/win-x64/native"
91
+ "C:/Program Files/Microsoft EdgeWebView/runtimes/win-x64/native"
92
+ )
93
+
94
+ if(WEBVIEW2_INCLUDE_DIR)
95
+ message(STATUS "Found WebView2 headers at: ${WEBVIEW2_INCLUDE_DIR}")
96
+ target_include_directories({{PROJECT_NAME}} PRIVATE ${WEBVIEW2_INCLUDE_DIR})
97
+ else()
98
+ message(WARNING "WebView2 headers not found. Building may fail.")
99
+ message(STATUS "Please install WebView2 SDK via NuGet:")
100
+ message(STATUS " nuget install Microsoft.Web.WebView2 -OutputDirectory packages")
101
+ endif()
102
+
103
+ target_link_libraries({{PROJECT_NAME}} PRIVATE ole32 shell32 shlwapi user32 version)
104
+
105
+ # Set subsystem to Windows for release builds (no console window)
106
+ if(NOT PLUSUI_DEV_MODE)
107
+ set_target_properties({{PROJECT_NAME}} PROPERTIES
108
+ WIN32_EXECUTABLE TRUE
109
+ )
110
+ endif()
111
+ elseif(APPLE)
112
+ # macOS: WebKit
113
+ find_library(WEBKIT_LIBRARY WebKit REQUIRED)
114
+ find_library(COCOA_LIBRARY Cocoa REQUIRED)
115
+ target_link_libraries({{PROJECT_NAME}} PRIVATE ${WEBKIT_LIBRARY} ${COCOA_LIBRARY})
116
+
117
+ # Create app bundle for production
118
+ if(NOT PLUSUI_DEV_MODE)
119
+ set_target_properties({{PROJECT_NAME}} PROPERTIES
120
+ MACOSX_BUNDLE TRUE
121
+ MACOSX_BUNDLE_BUNDLE_NAME "{{PROJECT_NAME}}"
122
+ MACOSX_BUNDLE_BUNDLE_VERSION "{{PROJECT_VERSION}}"
123
+ MACOSX_BUNDLE_GUI_IDENTIFIER "com.plusui.{{PROJECT_NAME_LOWER}}"
124
+ )
125
+ endif()
126
+ else()
127
+ # Linux: GTK + WebKitGTK
128
+ find_package(PkgConfig REQUIRED)
129
+ pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
130
+ pkg_check_modules(WEBKIT2 REQUIRED webkit2gtk-4.0)
131
+ target_include_directories({{PROJECT_NAME}} PRIVATE ${GTK3_INCLUDE_DIRS} ${WEBKIT2_INCLUDE_DIRS})
132
+ target_link_libraries({{PROJECT_NAME}} PRIVATE ${GTK3_LIBRARIES} ${WEBKIT2_LIBRARIES})
133
+ endif()
134
+
135
+ # Copy frontend dist files to build directory after build
136
+ if(EXISTS "${CMAKE_SOURCE_DIR}/frontend/dist")
137
+ add_custom_command(TARGET {{PROJECT_NAME}} POST_BUILD
138
+ COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:{{PROJECT_NAME}}>/frontend"
139
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
140
+ "${CMAKE_SOURCE_DIR}/frontend/dist"
141
+ "$<TARGET_FILE_DIR:{{PROJECT_NAME}}>/frontend"
142
+ COMMENT "Copying frontend files to build directory"
143
+ )
144
+ endif()
145
+
146
+ # Set output directories for organized builds
147
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
148
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
149
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
150
+
151
+
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{PROJECT_NAME}}</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "{{PROJECT_NAME_LOWER}}-frontend",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "react": "^18.2.0",
13
+ "react-dom": "^18.2.0",
14
+ "plusui-native-core": "{{PLUSUI_CORE_PATH}}"
15
+ },
16
+ "devDependencies": {
17
+ "@types/react": "^18.2.0",
18
+ "@types/react-dom": "^18.2.0",
19
+ "@vitejs/plugin-react": "^4.2.0",
20
+ "typescript": "^5.3.0",
21
+ "vite": "^5.0.0"
22
+ }
23
+ }
24
+
@@ -0,0 +1,134 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { win, browser, router, app } from 'plusui-native-core';
3
+
4
+ // Define routes for your app (optional - for SPA routing)
5
+ const routes = {
6
+ '/': 'http://localhost:5173',
7
+ '/settings': 'http://localhost:5173/settings',
8
+ '/about': 'http://localhost:5173/about',
9
+ };
10
+
11
+ function App() {
12
+ const [windowSize, setWindowSize] = useState({ width: 0, height: 0 });
13
+ const [windowPos, setWindowPos] = useState({ x: 0, y: 0 });
14
+ const [currentUrl, setCurrentUrl] = useState('');
15
+ const [canGoBack, setCanGoBack] = useState(false);
16
+ const [canGoForward, setCanGoForward] = useState(false);
17
+
18
+ useEffect(() => {
19
+ // Setup routes
20
+ router.setRoutes(routes);
21
+
22
+ // Listen for navigation changes
23
+ const unsub = browser.onNavigate((url) => {
24
+ setCurrentUrl(url);
25
+ browser.canGoBack().then(setCanGoBack);
26
+ browser.canGoForward().then(setCanGoForward);
27
+ });
28
+
29
+ // Get initial state
30
+ browser.getUrl().then(setCurrentUrl);
31
+ browser.canGoBack().then(setCanGoBack);
32
+ browser.canGoForward().then(setCanGoForward);
33
+
34
+ return unsub;
35
+ }, []);
36
+
37
+ const handleMinimize = async () => await win.minimize();
38
+ const handleMaximize = async () => await win.maximize();
39
+ const handleClose = async () => await win.close();
40
+ const handleGetSize = async () => {
41
+ const size = await win.getSize();
42
+ setWindowSize(size);
43
+ };
44
+ const handleGetPosition = async () => {
45
+ const pos = await win.getPosition();
46
+ setWindowPos(pos);
47
+ };
48
+
49
+ // Browser navigation
50
+ const handleGoBack = async () => await browser.goBack();
51
+ const handleGoForward = async () => await browser.goForward();
52
+ const handleReload = async () => await browser.reload();
53
+
54
+ // Router navigation
55
+ const handleGoHome = async () => await router.push('/');
56
+ const handleGoSettings = async () => await router.push('/settings');
57
+
58
+ // App control
59
+ const handleQuit = async () => await app.quit();
60
+
61
+ return (
62
+ <div className="app">
63
+ <header className="app-header">
64
+ <h1>{{PROJECT_NAME}}</h1>
65
+ <p>Built with PlusUI Framework</p>
66
+ </header>
67
+
68
+ <main className="app-content">
69
+ <div className="card">
70
+ <h2>Window Controls</h2>
71
+ <div className="button-group">
72
+ <button onClick={handleMinimize} className="button">Minimize</button>
73
+ <button onClick={handleMaximize} className="button">Maximize</button>
74
+ <button onClick={handleClose} className="button button-danger">Close</button>
75
+ </div>
76
+ </div>
77
+
78
+ <div className="card">
79
+ <h2>Window Size</h2>
80
+ <button onClick={handleGetSize} className="button">Get Size</button>
81
+ {windowSize.width > 0 && (
82
+ <p className="info-text">Size: {windowSize.width} x {windowSize.height}</p>
83
+ )}
84
+ </div>
85
+
86
+ <div className="card">
87
+ <h2>Window Position</h2>
88
+ <div className="button-group">
89
+ <button onClick={handleGetPosition} className="button">Get Position</button>
90
+ <button onClick={() => win.setPosition(100, 100)} className="button">Move Left</button>
91
+ <button onClick={() => win.setPosition(800, 100)} className="button">Move Right</button>
92
+ </div>
93
+ {windowPos.x !== 0 && (
94
+ <p className="info-text">Position: {windowPos.x}, {windowPos.y}</p>
95
+ )}
96
+ </div>
97
+
98
+ <div className="card">
99
+ <h2>Browser Navigation</h2>
100
+ <p className="info-text">Current: {currentUrl}</p>
101
+ <div className="button-group">
102
+ <button onClick={handleGoBack} className="button" disabled={!canGoBack}>Back</button>
103
+ <button onClick={handleGoForward} className="button" disabled={!canGoForward}>Forward</button>
104
+ <button onClick={handleReload} className="button">Reload</button>
105
+ </div>
106
+ </div>
107
+
108
+ <div className="card">
109
+ <h2>Router (SPA Navigation)</h2>
110
+ <div className="button-group">
111
+ <button onClick={handleGoHome} className="button">Home /</button>
112
+ <button onClick={handleGoSettings} className="button">Settings</button>
113
+ </div>
114
+ <p style={{ fontSize: '0.85em', color: '#666', marginTop: '10px' }}>
115
+ Define routes with <code>router.setRoutes({'{ ... }'})</code> then navigate with <code>router.push('/path')</code>
116
+ </p>
117
+ </div>
118
+
119
+ <div className="card">
120
+ <h2>App Control</h2>
121
+ <button onClick={handleQuit} className="button button-danger">Quit App</button>
122
+ </div>
123
+
124
+ <div className="info">
125
+ <p>Edit <code>frontend/src/App.tsx</code> to modify the UI.</p>
126
+ <p>Edit <code>main.cpp</code> to add C++ functionality.</p>
127
+ </div>
128
+ </main>
129
+ </div>
130
+ );
131
+ }
132
+
133
+ export default App;
134
+
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import App from './App';
4
+ import './styles/app.css';
5
+
6
+ ReactDOM.createRoot(document.getElementById('root')!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>,
10
+ );
@@ -0,0 +1,140 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ body {
8
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
9
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
10
+ sans-serif;
11
+ -webkit-font-smoothing: antialiased;
12
+ -moz-osx-font-smoothing: grayscale;
13
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
14
+ color: #fff;
15
+ min-height: 100vh;
16
+ }
17
+
18
+ .app {
19
+ display: flex;
20
+ flex-direction: column;
21
+ min-height: 100vh;
22
+ }
23
+
24
+ .app-header {
25
+ padding: 3rem 2rem;
26
+ text-align: center;
27
+ }
28
+
29
+ .app-header h1 {
30
+ font-size: 3rem;
31
+ font-weight: 700;
32
+ margin-bottom: 0.5rem;
33
+ text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
34
+ }
35
+
36
+ .app-header p {
37
+ font-size: 1.2rem;
38
+ opacity: 0.9;
39
+ }
40
+
41
+ .app-content {
42
+ flex: 1;
43
+ display: flex;
44
+ flex-direction: column;
45
+ align-items: center;
46
+ justify-content: center;
47
+ padding: 2rem;
48
+ gap: 2rem;
49
+ }
50
+
51
+ .card {
52
+ background: rgba(255, 255, 255, 0.1);
53
+ backdrop-filter: blur(10px);
54
+ border-radius: 1rem;
55
+ padding: 2rem;
56
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
57
+ border: 1px solid rgba(255, 255, 255, 0.2);
58
+ min-width: 400px;
59
+ text-align: center;
60
+ }
61
+
62
+ .card h2 {
63
+ margin-bottom: 1rem;
64
+ font-size: 1.3rem;
65
+ font-weight: 600;
66
+ }
67
+
68
+ .button-group {
69
+ display: flex;
70
+ gap: 0.75rem;
71
+ justify-content: center;
72
+ flex-wrap: wrap;
73
+ }
74
+
75
+ .button {
76
+ background: rgba(255, 255, 255, 0.2);
77
+ color: #fff;
78
+ border: 2px solid rgba(255, 255, 255, 0.3);
79
+ padding: 0.75rem 1.5rem;
80
+ font-size: 1rem;
81
+ font-weight: 600;
82
+ border-radius: 0.5rem;
83
+ cursor: pointer;
84
+ transition: all 0.3s ease;
85
+ }
86
+
87
+ .button:hover {
88
+ background: rgba(255, 255, 255, 0.3);
89
+ transform: translateY(-2px);
90
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
91
+ }
92
+
93
+ .button:active {
94
+ transform: translateY(0);
95
+ }
96
+
97
+ .button-danger {
98
+ background: rgba(231, 76, 60, 0.6);
99
+ border-color: rgba(231, 76, 60, 0.8);
100
+ }
101
+
102
+ .button-danger:hover {
103
+ background: rgba(231, 76, 60, 0.8);
104
+ }
105
+
106
+ .info-text {
107
+ margin-top: 1rem;
108
+ padding: 0.75rem 1rem;
109
+ background: rgba(255, 255, 255, 0.15);
110
+ border-radius: 0.5rem;
111
+ font-size: 1rem;
112
+ animation: fadeIn 0.3s ease;
113
+ }
114
+
115
+ @keyframes fadeIn {
116
+ from {
117
+ opacity: 0;
118
+ transform: translateY(-10px);
119
+ }
120
+ to {
121
+ opacity: 1;
122
+ transform: translateY(0);
123
+ }
124
+ }
125
+
126
+ .info {
127
+ text-align: center;
128
+ opacity: 0.8;
129
+ }
130
+
131
+ .info p {
132
+ margin: 0.5rem 0;
133
+ }
134
+
135
+ .info code {
136
+ background: rgba(0, 0, 0, 0.2);
137
+ padding: 0.2rem 0.5rem;
138
+ border-radius: 0.25rem;
139
+ font-family: 'Courier New', monospace;
140
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "resolveJsonModule": true,
11
+ "isolatedModules": true,
12
+ "noEmit": true,
13
+ "jsx": "react-jsx",
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true
18
+ },
19
+ "include": ["src"],
20
+ "references": [{ "path": "./tsconfig.node.json" }]
21
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true,
8
+ "strict": true
9
+ },
10
+ "include": ["vite.config.ts"]
11
+ }
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ build: {
7
+ outDir: 'dist',
8
+ emptyOutDir: true,
9
+ },
10
+ server: {
11
+ port: 5173,
12
+ strictPort: true,
13
+ },
14
+ });