imxc 0.5.4 → 0.6.1
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.
- package/dist/compile.d.ts +8 -0
- package/dist/compile.js +285 -25
- package/dist/components.js +597 -45
- package/dist/diagnostics.js +3 -2
- package/dist/emitter.d.ts +6 -3
- package/dist/emitter.js +1454 -322
- package/dist/index.js +34 -7
- package/dist/init.d.ts +7 -1
- package/dist/init.js +43 -455
- package/dist/ir.d.ts +437 -5
- package/dist/lowering.d.ts +4 -3
- package/dist/lowering.js +770 -57
- package/dist/parser.d.ts +1 -0
- package/dist/templates/async.d.ts +1 -0
- package/dist/templates/async.js +228 -0
- package/dist/templates/custom.d.ts +15 -0
- package/dist/templates/custom.js +945 -0
- package/dist/templates/filedialog.d.ts +1 -0
- package/dist/templates/filedialog.js +216 -0
- package/dist/templates/hotreload.d.ts +1 -0
- package/dist/templates/hotreload.js +400 -0
- package/dist/templates/index.d.ts +16 -0
- package/dist/templates/index.js +553 -0
- package/dist/templates/minimal.d.ts +1 -0
- package/dist/templates/minimal.js +165 -0
- package/dist/templates/networking.d.ts +1 -0
- package/dist/templates/networking.js +244 -0
- package/dist/templates/persistence.d.ts +1 -0
- package/dist/templates/persistence.js +238 -0
- package/dist/validator.d.ts +1 -0
- package/dist/validator.js +51 -22
- package/dist/watch.d.ts +2 -1
- package/dist/watch.js +21 -4
- package/package.json +2 -4
package/dist/index.js
CHANGED
|
@@ -4,11 +4,31 @@ import * as path from 'node:path';
|
|
|
4
4
|
import { initProject, addToProject } from './init.js';
|
|
5
5
|
import { compile } from './compile.js';
|
|
6
6
|
import { startWatch } from './watch.js';
|
|
7
|
-
|
|
7
|
+
import { promptProjectName, promptTemplateName, TEMPLATES } from './templates/index.js';
|
|
8
|
+
// Handle `imxc templates` — list available templates
|
|
9
|
+
if (process.argv[2] === 'templates') {
|
|
10
|
+
console.log('Available templates:\n');
|
|
11
|
+
TEMPLATES.forEach(t => {
|
|
12
|
+
console.log(` ${t.name} — ${t.description}`);
|
|
13
|
+
});
|
|
14
|
+
console.log('\nUsage: imxc init <project-name> --template=<name>');
|
|
15
|
+
console.log('Combine: imxc init <project-name> --template=async,persistence');
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
// Handle `imxc init [dir] [--template=<name>]` subcommand
|
|
8
19
|
if (process.argv[2] === 'init') {
|
|
9
|
-
const
|
|
20
|
+
const { values, positionals } = parseArgs({
|
|
21
|
+
args: process.argv.slice(3),
|
|
22
|
+
allowPositionals: true,
|
|
23
|
+
options: { template: { type: 'string', short: 't' } },
|
|
24
|
+
});
|
|
25
|
+
let dir = positionals[0];
|
|
26
|
+
if (!dir) {
|
|
27
|
+
dir = await promptProjectName();
|
|
28
|
+
}
|
|
10
29
|
const absDir = path.resolve(dir);
|
|
11
|
-
|
|
30
|
+
const templateName = values.template ?? await promptTemplateName();
|
|
31
|
+
initProject(absDir, path.basename(absDir), templateName);
|
|
12
32
|
process.exit(0);
|
|
13
33
|
}
|
|
14
34
|
// Handle `imxc add [dir]` subcommand
|
|
@@ -28,10 +48,13 @@ if (process.argv[2] === 'watch') {
|
|
|
28
48
|
const { values } = parseArgs({
|
|
29
49
|
args: process.argv.slice(4),
|
|
30
50
|
allowPositionals: false,
|
|
31
|
-
options: {
|
|
51
|
+
options: {
|
|
52
|
+
output: { type: 'string', short: 'o' },
|
|
53
|
+
build: { type: 'string', short: 'b' },
|
|
54
|
+
},
|
|
32
55
|
});
|
|
33
56
|
const outputDir = values.output ?? '.';
|
|
34
|
-
startWatch(path.resolve(watchDir), path.resolve(outputDir));
|
|
57
|
+
startWatch(path.resolve(watchDir), path.resolve(outputDir), values.build);
|
|
35
58
|
}
|
|
36
59
|
else {
|
|
37
60
|
// Default: build command
|
|
@@ -41,13 +64,17 @@ else {
|
|
|
41
64
|
});
|
|
42
65
|
if (positionals.length === 0) {
|
|
43
66
|
console.error('Usage: imxc <input.tsx ...> -o <output-dir>');
|
|
44
|
-
console.error(' imxc init [project-dir]');
|
|
67
|
+
console.error(' imxc init [project-dir] [--template=<name[,name,...]>]');
|
|
68
|
+
console.error(' imxc templates');
|
|
45
69
|
console.error(' imxc add [project-dir]');
|
|
46
|
-
console.error(' imxc watch <dir> -o <output-dir>');
|
|
70
|
+
console.error(' imxc watch <dir> -o <output-dir> [--build <cmd>]');
|
|
47
71
|
process.exit(1);
|
|
48
72
|
}
|
|
49
73
|
const outputDir = values.output ?? '.';
|
|
50
74
|
const result = compile(positionals, outputDir);
|
|
75
|
+
if (result.warnings.length > 0) {
|
|
76
|
+
result.warnings.forEach(w => console.warn(w));
|
|
77
|
+
}
|
|
51
78
|
if (!result.success) {
|
|
52
79
|
result.errors.forEach(e => console.error(e));
|
|
53
80
|
process.exit(1);
|
package/dist/init.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
+
import './templates/minimal.js';
|
|
2
|
+
import './templates/async.js';
|
|
3
|
+
import './templates/persistence.js';
|
|
4
|
+
import './templates/networking.js';
|
|
5
|
+
import './templates/hotreload.js';
|
|
6
|
+
import './templates/filedialog.js';
|
|
1
7
|
export declare function addToProject(projectDir: string): void;
|
|
2
|
-
export declare function initProject(projectDir: string, projectName?: string): void;
|
|
8
|
+
export declare function initProject(projectDir: string, projectName?: string, templateName?: string): void;
|
package/dist/init.js
CHANGED
|
@@ -1,428 +1,13 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
struct AppState {
|
|
12
|
-
int count = 0;
|
|
13
|
-
float speed = 5.0f;
|
|
14
|
-
std::function<void()> onIncrement;
|
|
15
|
-
};
|
|
16
|
-
`;
|
|
17
|
-
const MAIN_CPP = `#include <imx/runtime.h>
|
|
18
|
-
#include <imx/renderer.h>
|
|
19
|
-
|
|
20
|
-
#include <imgui.h>
|
|
21
|
-
#include <imgui_impl_glfw.h>
|
|
22
|
-
#include <imgui_impl_opengl3.h>
|
|
23
|
-
#include <GLFW/glfw3.h>
|
|
24
|
-
|
|
25
|
-
#include "AppState.h"
|
|
26
|
-
|
|
27
|
-
struct App {
|
|
28
|
-
GLFWwindow* window = nullptr;
|
|
29
|
-
ImGuiIO* io = nullptr;
|
|
30
|
-
imx::Runtime runtime;
|
|
31
|
-
AppState state;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
static void render_frame(App& app) {
|
|
35
|
-
glfwMakeContextCurrent(app.window);
|
|
36
|
-
if (glfwGetWindowAttrib(app.window, GLFW_ICONIFIED) != 0) return;
|
|
37
|
-
|
|
38
|
-
int fb_w = 0, fb_h = 0;
|
|
39
|
-
glfwGetFramebufferSize(app.window, &fb_w, &fb_h);
|
|
40
|
-
if (fb_w <= 0 || fb_h <= 0) return;
|
|
41
|
-
|
|
42
|
-
ImGui_ImplOpenGL3_NewFrame();
|
|
43
|
-
ImGui_ImplGlfw_NewFrame();
|
|
44
|
-
ImGui::NewFrame();
|
|
45
|
-
|
|
46
|
-
imx::render_root(app.runtime, app.state);
|
|
47
|
-
|
|
48
|
-
ImGui::Render();
|
|
49
|
-
glViewport(0, 0, fb_w, fb_h);
|
|
50
|
-
glClearColor(0.12F, 0.12F, 0.15F, 1.0F);
|
|
51
|
-
glClear(GL_COLOR_BUFFER_BIT);
|
|
52
|
-
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
|
53
|
-
|
|
54
|
-
if ((app.io->ConfigFlags & ImGuiConfigFlags_ViewportsEnable) != 0) {
|
|
55
|
-
ImGui::UpdatePlatformWindows();
|
|
56
|
-
ImGui::RenderPlatformWindowsDefault();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
glfwMakeContextCurrent(app.window);
|
|
60
|
-
glfwSwapBuffers(app.window);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
static void window_size_callback(GLFWwindow* window, int, int) {
|
|
64
|
-
auto* app = static_cast<App*>(glfwGetWindowUserPointer(window));
|
|
65
|
-
if (app) render_frame(*app);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
int main() {
|
|
69
|
-
if (glfwInit() == 0) return 1;
|
|
70
|
-
|
|
71
|
-
const char* glsl_version = "#version 150";
|
|
72
|
-
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
73
|
-
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
|
74
|
-
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
75
|
-
#ifdef __APPLE__
|
|
76
|
-
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
|
77
|
-
#endif
|
|
78
|
-
|
|
79
|
-
GLFWwindow* window = glfwCreateWindow(800, 600, "APP_NAME", nullptr, nullptr);
|
|
80
|
-
if (!window) { glfwTerminate(); return 1; }
|
|
81
|
-
glfwMakeContextCurrent(window);
|
|
82
|
-
glfwSwapInterval(1);
|
|
83
|
-
|
|
84
|
-
IMGUI_CHECKVERSION();
|
|
85
|
-
ImGui::CreateContext();
|
|
86
|
-
ImGuiIO& io = ImGui::GetIO();
|
|
87
|
-
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
|
88
|
-
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
|
89
|
-
|
|
90
|
-
ImGui::StyleColorsDark();
|
|
91
|
-
ImGuiStyle& style = ImGui::GetStyle();
|
|
92
|
-
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
|
|
93
|
-
style.WindowRounding = 0.0F;
|
|
94
|
-
style.Colors[ImGuiCol_WindowBg].w = 1.0F;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
|
98
|
-
ImGui_ImplOpenGL3_Init(glsl_version);
|
|
99
|
-
|
|
100
|
-
App app;
|
|
101
|
-
app.window = window;
|
|
102
|
-
app.io = &io;
|
|
103
|
-
glfwSetWindowUserPointer(window, &app);
|
|
104
|
-
glfwSetWindowSizeCallback(window, window_size_callback);
|
|
105
|
-
app.state.onIncrement = [&]() { app.state.count++; };
|
|
106
|
-
|
|
107
|
-
while (glfwWindowShouldClose(window) == 0) {
|
|
108
|
-
if (app.runtime.needs_frame()) {
|
|
109
|
-
glfwPollEvents();
|
|
110
|
-
} else {
|
|
111
|
-
glfwWaitEventsTimeout(0.1);
|
|
112
|
-
}
|
|
113
|
-
render_frame(app);
|
|
114
|
-
app.runtime.frame_rendered(ImGui::IsAnyItemActive());
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
ImGui_ImplOpenGL3_Shutdown();
|
|
118
|
-
ImGui_ImplGlfw_Shutdown();
|
|
119
|
-
ImGui::DestroyContext();
|
|
120
|
-
glfwDestroyWindow(window);
|
|
121
|
-
glfwTerminate();
|
|
122
|
-
return 0;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
#ifdef _WIN32
|
|
126
|
-
#include <windows.h>
|
|
127
|
-
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { return main(); }
|
|
128
|
-
#endif
|
|
129
|
-
`;
|
|
130
|
-
const APP_TSX = `export default function App(props: AppState) {
|
|
131
|
-
const [showAbout, setShowAbout] = useState(false);
|
|
132
|
-
|
|
133
|
-
return (
|
|
134
|
-
<DockSpace>
|
|
135
|
-
<Window title="Controls">
|
|
136
|
-
<Column gap={8}>
|
|
137
|
-
<Text>Count: {props.count}</Text>
|
|
138
|
-
<Button title="Increment" onPress={props.onIncrement} />
|
|
139
|
-
<SliderFloat label="Speed" value={props.speed} min={0} max={100} />
|
|
140
|
-
<Separator />
|
|
141
|
-
<Button title="About" onPress={() => setShowAbout(!showAbout)} />
|
|
142
|
-
</Column>
|
|
143
|
-
</Window>
|
|
144
|
-
{showAbout && <Window title="About">
|
|
145
|
-
<Text>Built with IMX</Text>
|
|
146
|
-
<Button title="Close" onPress={() => setShowAbout(false)} />
|
|
147
|
-
</Window>}
|
|
148
|
-
</DockSpace>
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
`;
|
|
152
|
-
const IMX_DTS = `// imx.d.ts — Type definitions for IMX components
|
|
153
|
-
|
|
154
|
-
interface Style {
|
|
155
|
-
padding?: number;
|
|
156
|
-
paddingHorizontal?: number;
|
|
157
|
-
paddingVertical?: number;
|
|
158
|
-
gap?: number;
|
|
159
|
-
width?: number;
|
|
160
|
-
height?: number;
|
|
161
|
-
minWidth?: number;
|
|
162
|
-
minHeight?: number;
|
|
163
|
-
backgroundColor?: [number, number, number, number];
|
|
164
|
-
textColor?: [number, number, number, number];
|
|
165
|
-
fontSize?: number;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
declare function useState<T>(initial: T): [T, (value: T) => void];
|
|
169
|
-
|
|
170
|
-
interface AppState {
|
|
171
|
-
count: number;
|
|
172
|
-
speed: number;
|
|
173
|
-
onIncrement: () => void;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
interface WindowProps { title: string; open?: boolean; onClose?: () => void; noTitleBar?: boolean; noResize?: boolean; noMove?: boolean; noCollapse?: boolean; noDocking?: boolean; noScrollbar?: boolean; style?: Style; children?: any; }
|
|
177
|
-
interface ViewProps { style?: Style; children?: any; }
|
|
178
|
-
interface RowProps { gap?: number; style?: Style; children?: any; }
|
|
179
|
-
interface ColumnProps { gap?: number; style?: Style; children?: any; }
|
|
180
|
-
interface TextProps { style?: Style; children?: any; }
|
|
181
|
-
interface ButtonProps { title: string; onPress: () => void; disabled?: boolean; style?: Style; }
|
|
182
|
-
interface TextInputProps { value: string; onChange?: (v: string) => void; label?: string; placeholder?: string; style?: Style; }
|
|
183
|
-
interface CheckboxProps { value: boolean; onChange?: (v: boolean) => void; label?: string; style?: Style; }
|
|
184
|
-
interface SeparatorProps {}
|
|
185
|
-
interface PopupProps { id: string; style?: Style; children?: any; }
|
|
186
|
-
interface DockSpaceProps { style?: Style; children?: any; }
|
|
187
|
-
interface DockLayoutProps { children?: any; }
|
|
188
|
-
interface DockSplitProps { direction: "horizontal" | "vertical"; size: number; children?: any; }
|
|
189
|
-
interface DockPanelProps { children?: any; }
|
|
190
|
-
interface ThemeProps {
|
|
191
|
-
preset: string;
|
|
192
|
-
accentColor?: [number, number, number, number];
|
|
193
|
-
backgroundColor?: [number, number, number, number];
|
|
194
|
-
textColor?: [number, number, number, number];
|
|
195
|
-
borderColor?: [number, number, number, number];
|
|
196
|
-
surfaceColor?: [number, number, number, number];
|
|
197
|
-
rounding?: number;
|
|
198
|
-
borderSize?: number;
|
|
199
|
-
spacing?: number;
|
|
200
|
-
children?: any;
|
|
201
|
-
}
|
|
202
|
-
interface MenuBarProps { children?: any; }
|
|
203
|
-
interface MenuProps { label: string; children?: any; }
|
|
204
|
-
interface MenuItemProps { label: string; onPress?: () => void; shortcut?: string; }
|
|
205
|
-
interface TableProps { columns: string[]; scrollY?: boolean; noBorders?: boolean; noRowBg?: boolean; style?: Style; children?: any; }
|
|
206
|
-
interface TableRowProps { key?: number | string; children?: any; }
|
|
207
|
-
interface TabBarProps { style?: Style; children?: any; }
|
|
208
|
-
interface TabItemProps { label: string; children?: any; }
|
|
209
|
-
interface TreeNodeProps { label: string; children?: any; }
|
|
210
|
-
interface CollapsingHeaderProps { label: string; children?: any; }
|
|
211
|
-
interface SliderFloatProps { label: string; value: number; onChange?: (v: number) => void; min: number; max: number; style?: Style; }
|
|
212
|
-
interface SliderIntProps { label: string; value: number; onChange?: (v: number) => void; min: number; max: number; style?: Style; }
|
|
213
|
-
interface DragFloatProps { label: string; value: number; onChange?: (v: number) => void; speed?: number; style?: Style; }
|
|
214
|
-
interface DragIntProps { label: string; value: number; onChange?: (v: number) => void; speed?: number; style?: Style; }
|
|
215
|
-
interface ComboProps { label: string; value: number; onChange?: (v: number) => void; items: string[]; style?: Style; }
|
|
216
|
-
interface InputIntProps { label: string; value: number; onChange?: (v: number) => void; style?: Style; }
|
|
217
|
-
interface InputFloatProps { label: string; value: number; onChange?: (v: number) => void; style?: Style; }
|
|
218
|
-
interface ColorEditProps { label: string; value: number[]; onChange: (v: number[]) => void; style?: Style; }
|
|
219
|
-
interface ListBoxProps { label: string; value: number; onChange?: (v: number) => void; items: string[]; style?: Style; }
|
|
220
|
-
interface ProgressBarProps { value: number; overlay?: string; style?: Style; }
|
|
221
|
-
interface TooltipProps { text: string; }
|
|
222
|
-
interface BulletTextProps { style?: Style; children?: any; }
|
|
223
|
-
interface LabelTextProps { label: string; value: string; }
|
|
224
|
-
interface SelectableProps { label: string; selected?: boolean; onSelect?: () => void; style?: Style; }
|
|
225
|
-
interface RadioProps { label: string; value: number; index: number; onChange?: (v: number) => void; style?: Style; }
|
|
226
|
-
interface InputTextMultilineProps { label: string; value: string; style?: Style; }
|
|
227
|
-
interface ColorPickerProps { label: string; value: number[]; style?: Style; }
|
|
228
|
-
interface PlotLinesProps { label: string; values: number[]; overlay?: string; style?: Style; }
|
|
229
|
-
interface PlotHistogramProps { label: string; values: number[]; overlay?: string; style?: Style; }
|
|
230
|
-
interface ModalProps { title: string; open?: boolean; onClose?: () => void; style?: Style; children?: any; }
|
|
231
|
-
interface ImageProps { src: string; embed?: boolean; width?: number; height?: number; }
|
|
232
|
-
interface GroupProps { style?: Style; children?: any; }
|
|
233
|
-
interface IDProps { scope: string | number; children?: any; }
|
|
234
|
-
interface DragDropSourceProps { type: string; payload: number | string; children?: any; }
|
|
235
|
-
interface DragDropTargetProps { type: string; onDrop: (payload: any) => void; children?: any; }
|
|
236
|
-
interface CanvasProps { width: number; height: number; style?: Style; children?: any; }
|
|
237
|
-
interface DrawLineProps { p1: [number, number]; p2: [number, number]; color: [number, number, number, number]; thickness?: number; }
|
|
238
|
-
interface DrawRectProps { min: [number, number]; max: [number, number]; color: [number, number, number, number]; filled?: boolean; thickness?: number; rounding?: number; }
|
|
239
|
-
interface DrawCircleProps { center: [number, number]; radius: number; color: [number, number, number, number]; filled?: boolean; thickness?: number; }
|
|
240
|
-
interface DrawTextProps { pos: [number, number]; text: string; color: [number, number, number, number]; }
|
|
241
|
-
interface StyleColorProps {
|
|
242
|
-
text?: [number, number, number, number];
|
|
243
|
-
textDisabled?: [number, number, number, number];
|
|
244
|
-
windowBg?: [number, number, number, number];
|
|
245
|
-
frameBg?: [number, number, number, number];
|
|
246
|
-
frameBgHovered?: [number, number, number, number];
|
|
247
|
-
frameBgActive?: [number, number, number, number];
|
|
248
|
-
titleBg?: [number, number, number, number];
|
|
249
|
-
titleBgActive?: [number, number, number, number];
|
|
250
|
-
button?: [number, number, number, number];
|
|
251
|
-
buttonHovered?: [number, number, number, number];
|
|
252
|
-
buttonActive?: [number, number, number, number];
|
|
253
|
-
header?: [number, number, number, number];
|
|
254
|
-
headerHovered?: [number, number, number, number];
|
|
255
|
-
headerActive?: [number, number, number, number];
|
|
256
|
-
separator?: [number, number, number, number];
|
|
257
|
-
checkMark?: [number, number, number, number];
|
|
258
|
-
sliderGrab?: [number, number, number, number];
|
|
259
|
-
border?: [number, number, number, number];
|
|
260
|
-
popupBg?: [number, number, number, number];
|
|
261
|
-
tab?: [number, number, number, number];
|
|
262
|
-
children?: any;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
declare function Window(props: WindowProps): any;
|
|
266
|
-
declare function View(props: ViewProps): any;
|
|
267
|
-
declare function Row(props: RowProps): any;
|
|
268
|
-
declare function Column(props: ColumnProps): any;
|
|
269
|
-
declare function Text(props: TextProps): any;
|
|
270
|
-
declare function Button(props: ButtonProps): any;
|
|
271
|
-
declare function TextInput(props: TextInputProps): any;
|
|
272
|
-
declare function Checkbox(props: CheckboxProps): any;
|
|
273
|
-
declare function Separator(props: SeparatorProps): any;
|
|
274
|
-
declare function Popup(props: PopupProps): any;
|
|
275
|
-
declare function DockSpace(props: DockSpaceProps): any;
|
|
276
|
-
declare function DockLayout(props: DockLayoutProps): any;
|
|
277
|
-
declare function DockSplit(props: DockSplitProps): any;
|
|
278
|
-
declare function DockPanel(props: DockPanelProps): any;
|
|
279
|
-
declare function Theme(props: ThemeProps): any;
|
|
280
|
-
declare function MenuBar(props: MenuBarProps): any;
|
|
281
|
-
declare function Menu(props: MenuProps): any;
|
|
282
|
-
declare function MenuItem(props: MenuItemProps): any;
|
|
283
|
-
declare function Table(props: TableProps): any;
|
|
284
|
-
declare function TableRow(props: TableRowProps): any;
|
|
285
|
-
declare function TabBar(props: TabBarProps): any;
|
|
286
|
-
declare function TabItem(props: TabItemProps): any;
|
|
287
|
-
declare function TreeNode(props: TreeNodeProps): any;
|
|
288
|
-
declare function CollapsingHeader(props: CollapsingHeaderProps): any;
|
|
289
|
-
declare function SliderFloat(props: SliderFloatProps): any;
|
|
290
|
-
declare function SliderInt(props: SliderIntProps): any;
|
|
291
|
-
declare function DragFloat(props: DragFloatProps): any;
|
|
292
|
-
declare function DragInt(props: DragIntProps): any;
|
|
293
|
-
declare function Combo(props: ComboProps): any;
|
|
294
|
-
declare function InputInt(props: InputIntProps): any;
|
|
295
|
-
declare function InputFloat(props: InputFloatProps): any;
|
|
296
|
-
declare function ColorEdit(props: ColorEditProps): any;
|
|
297
|
-
declare function ListBox(props: ListBoxProps): any;
|
|
298
|
-
declare function ProgressBar(props: ProgressBarProps): any;
|
|
299
|
-
declare function Tooltip(props: TooltipProps): any;
|
|
300
|
-
declare function BulletText(props: BulletTextProps): any;
|
|
301
|
-
declare function LabelText(props: LabelTextProps): any;
|
|
302
|
-
declare function Selectable(props: SelectableProps): any;
|
|
303
|
-
declare function Radio(props: RadioProps): any;
|
|
304
|
-
declare function InputTextMultiline(props: InputTextMultilineProps): any;
|
|
305
|
-
declare function ColorPicker(props: ColorPickerProps): any;
|
|
306
|
-
declare function PlotLines(props: PlotLinesProps): any;
|
|
307
|
-
declare function PlotHistogram(props: PlotHistogramProps): any;
|
|
308
|
-
declare function Modal(props: ModalProps): any;
|
|
309
|
-
declare function Image(props: ImageProps): any;
|
|
310
|
-
declare function Group(props: GroupProps): any;
|
|
311
|
-
declare function ID(props: IDProps): any;
|
|
312
|
-
declare function StyleColor(props: StyleColorProps): any;
|
|
313
|
-
declare function Canvas(props: CanvasProps): any;
|
|
314
|
-
declare function DrawLine(props: DrawLineProps): any;
|
|
315
|
-
declare function DrawRect(props: DrawRectProps): any;
|
|
316
|
-
declare function DrawCircle(props: DrawCircleProps): any;
|
|
317
|
-
declare function DrawText(props: DrawTextProps): any;
|
|
318
|
-
|
|
319
|
-
interface StyleVarProps {
|
|
320
|
-
alpha?: number;
|
|
321
|
-
windowPadding?: [number, number];
|
|
322
|
-
windowRounding?: number;
|
|
323
|
-
framePadding?: [number, number];
|
|
324
|
-
frameRounding?: number;
|
|
325
|
-
frameBorderSize?: number;
|
|
326
|
-
itemSpacing?: [number, number];
|
|
327
|
-
itemInnerSpacing?: [number, number];
|
|
328
|
-
indentSpacing?: number;
|
|
329
|
-
cellPadding?: [number, number];
|
|
330
|
-
tabRounding?: number;
|
|
331
|
-
children?: any;
|
|
332
|
-
}
|
|
333
|
-
declare function StyleVar(props: StyleVarProps): any;
|
|
334
|
-
declare function DragDropSource(props: DragDropSourceProps): any;
|
|
335
|
-
declare function DragDropTarget(props: DragDropTargetProps): any;
|
|
336
|
-
interface DisabledProps { disabled?: boolean; children?: any; }
|
|
337
|
-
interface ChildProps { id: string; width?: number; height?: number; border?: boolean; style?: Style; children?: any; }
|
|
338
|
-
declare function Disabled(props: DisabledProps): any;
|
|
339
|
-
declare function Child(props: ChildProps): any;
|
|
340
|
-
|
|
341
|
-
declare function resetLayout(): void;
|
|
342
|
-
|
|
343
|
-
// --- Custom native widgets ---
|
|
344
|
-
// Declare your C++ registered widgets here for type checking:
|
|
345
|
-
//
|
|
346
|
-
// interface KnobProps {
|
|
347
|
-
// value: number;
|
|
348
|
-
// onChange: (value: number) => void;
|
|
349
|
-
// min: number;
|
|
350
|
-
// max: number;
|
|
351
|
-
// width?: number;
|
|
352
|
-
// height?: number;
|
|
353
|
-
// }
|
|
354
|
-
// declare function Knob(props: KnobProps): any;
|
|
355
|
-
|
|
356
|
-
declare module "imx/jsx-runtime" {
|
|
357
|
-
export namespace JSX {
|
|
358
|
-
type Element = any;
|
|
359
|
-
interface IntrinsicElements { [tag: string]: any; }
|
|
360
|
-
interface ElementChildrenAttribute { children: {}; }
|
|
361
|
-
}
|
|
362
|
-
export function jsx(type: any, props: any, key?: any): any;
|
|
363
|
-
export function jsxs(type: any, props: any, key?: any): any;
|
|
364
|
-
export function Fragment(props: any): any;
|
|
365
|
-
}
|
|
366
|
-
`;
|
|
367
|
-
const TSCONFIG = `{
|
|
368
|
-
"compilerOptions": {
|
|
369
|
-
"target": "ES2022",
|
|
370
|
-
"lib": ["ES2022"],
|
|
371
|
-
"module": "ES2022",
|
|
372
|
-
"moduleResolution": "bundler",
|
|
373
|
-
"jsx": "react-jsx",
|
|
374
|
-
"jsxImportSource": "imx",
|
|
375
|
-
"strict": false,
|
|
376
|
-
"noEmit": true,
|
|
377
|
-
"skipLibCheck": true
|
|
378
|
-
},
|
|
379
|
-
"include": ["src/**/*.tsx", "src/imx.d.ts"]
|
|
380
|
-
}
|
|
381
|
-
`;
|
|
382
|
-
function cmakeTemplate(projectName, repoUrl) {
|
|
383
|
-
return `cmake_minimum_required(VERSION 3.25)
|
|
384
|
-
project(${projectName} LANGUAGES CXX)
|
|
385
|
-
|
|
386
|
-
set(CMAKE_CXX_STANDARD 20)
|
|
387
|
-
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
388
|
-
|
|
389
|
-
include(FetchContent)
|
|
390
|
-
set(FETCHCONTENT_QUIET OFF)
|
|
391
|
-
|
|
392
|
-
FetchContent_Declare(
|
|
393
|
-
imx
|
|
394
|
-
GIT_REPOSITORY ${repoUrl}
|
|
395
|
-
GIT_TAG main
|
|
396
|
-
GIT_SHALLOW TRUE
|
|
397
|
-
GIT_PROGRESS TRUE
|
|
398
|
-
)
|
|
399
|
-
message(STATUS "Fetching IMX (includes ImGui + GLFW)...")
|
|
400
|
-
FetchContent_MakeAvailable(imx)
|
|
401
|
-
|
|
402
|
-
include(ImxCompile)
|
|
403
|
-
|
|
404
|
-
imx_compile_tsx(GENERATED
|
|
405
|
-
SOURCES src/App.tsx
|
|
406
|
-
OUTPUT_DIR \${CMAKE_BINARY_DIR}/generated
|
|
407
|
-
)
|
|
408
|
-
|
|
409
|
-
add_executable(${projectName}
|
|
410
|
-
src/main.cpp
|
|
411
|
-
\${GENERATED}
|
|
412
|
-
)
|
|
413
|
-
set_target_properties(${projectName} PROPERTIES WIN32_EXECUTABLE $<CONFIG:Release>)
|
|
414
|
-
target_link_libraries(${projectName} PRIVATE imx::renderer)
|
|
415
|
-
target_include_directories(${projectName} PRIVATE \${CMAKE_BINARY_DIR}/generated \${CMAKE_CURRENT_SOURCE_DIR}/src)
|
|
416
|
-
|
|
417
|
-
# Copy public/ assets to output directory
|
|
418
|
-
add_custom_command(TARGET ${projectName} POST_BUILD
|
|
419
|
-
COMMAND \${CMAKE_COMMAND} -E copy_directory
|
|
420
|
-
\${CMAKE_CURRENT_SOURCE_DIR}/public
|
|
421
|
-
$<TARGET_FILE_DIR:${projectName}>
|
|
422
|
-
COMMENT "Copying public/ assets"
|
|
423
|
-
)
|
|
424
|
-
`;
|
|
425
|
-
}
|
|
3
|
+
import { TEMPLATES, APP_TSX, buildImxDts, TSCONFIG } from './templates/index.js';
|
|
4
|
+
import { generateCombined, FEATURES } from './templates/custom.js';
|
|
5
|
+
import './templates/minimal.js';
|
|
6
|
+
import './templates/async.js';
|
|
7
|
+
import './templates/persistence.js';
|
|
8
|
+
import './templates/networking.js';
|
|
9
|
+
import './templates/hotreload.js';
|
|
10
|
+
import './templates/filedialog.js';
|
|
426
11
|
export function addToProject(projectDir) {
|
|
427
12
|
const srcDir = path.join(projectDir, 'src');
|
|
428
13
|
if (fs.existsSync(path.join(srcDir, 'App.tsx'))) {
|
|
@@ -434,7 +19,11 @@ export function addToProject(projectDir) {
|
|
|
434
19
|
fs.mkdirSync(publicDir, { recursive: true });
|
|
435
20
|
// Write TSX source files only — no CMakeLists.txt or main.cpp
|
|
436
21
|
fs.writeFileSync(path.join(srcDir, 'App.tsx'), APP_TSX);
|
|
437
|
-
fs.writeFileSync(path.join(srcDir, 'imx.d.ts'),
|
|
22
|
+
fs.writeFileSync(path.join(srcDir, 'imx.d.ts'), buildImxDts(`interface AppState {
|
|
23
|
+
count: number;
|
|
24
|
+
speed: number;
|
|
25
|
+
onIncrement: () => void;
|
|
26
|
+
}`));
|
|
438
27
|
fs.writeFileSync(path.join(projectDir, 'tsconfig.json'), TSCONFIG);
|
|
439
28
|
console.log(`imxc: added IMX sources to project`);
|
|
440
29
|
console.log('');
|
|
@@ -450,7 +39,7 @@ export function addToProject(projectDir) {
|
|
|
450
39
|
console.log(' include(FetchContent)');
|
|
451
40
|
console.log(' FetchContent_Declare(imx');
|
|
452
41
|
console.log(' GIT_REPOSITORY https://github.com/bgocumlu/imx.git');
|
|
453
|
-
console.log(' GIT_TAG
|
|
42
|
+
console.log(' GIT_TAG v0.6.1');
|
|
454
43
|
console.log(' )');
|
|
455
44
|
console.log(' FetchContent_MakeAvailable(imx)');
|
|
456
45
|
console.log(' include(ImxCompile)');
|
|
@@ -478,37 +67,36 @@ export function addToProject(projectDir) {
|
|
|
478
67
|
console.log(' // In your frame loop, between NewFrame() and Render():');
|
|
479
68
|
console.log(' imx::render_root(runtime);');
|
|
480
69
|
}
|
|
481
|
-
export function initProject(projectDir, projectName) {
|
|
70
|
+
export function initProject(projectDir, projectName, templateName) {
|
|
482
71
|
const name = projectName ?? path.basename(projectDir);
|
|
483
|
-
const
|
|
484
|
-
if
|
|
485
|
-
|
|
72
|
+
const tpl = templateName ?? 'minimal';
|
|
73
|
+
// Check if directory already has content
|
|
74
|
+
if (fs.existsSync(projectDir)) {
|
|
75
|
+
const entries = fs.readdirSync(projectDir).filter(e => e !== '.git');
|
|
76
|
+
if (entries.length > 0) {
|
|
77
|
+
console.error('Error: directory is not empty.');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Check for comma-separated (combined template)
|
|
82
|
+
const parts = tpl.split(',').map(s => s.trim());
|
|
83
|
+
if (parts.length > 1) {
|
|
84
|
+
// Validate all parts are known features
|
|
85
|
+
const featureNames = FEATURES.map(f => f.name);
|
|
86
|
+
for (const p of parts) {
|
|
87
|
+
if (!featureNames.includes(p)) {
|
|
88
|
+
console.error(`Error: unknown feature "${p}". Combinable features: ${featureNames.join(', ')}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
generateCombined(parts, projectDir, name);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Single template — use existing generator
|
|
96
|
+
const entry = TEMPLATES.find(t => t.name === tpl);
|
|
97
|
+
if (!entry) {
|
|
98
|
+
console.error(`Error: unknown template "${tpl}". Available: ${TEMPLATES.map(t => t.name).join(', ')}`);
|
|
486
99
|
process.exit(1);
|
|
487
100
|
}
|
|
488
|
-
|
|
489
|
-
const publicDir = path.join(projectDir, 'public');
|
|
490
|
-
fs.mkdirSync(publicDir, { recursive: true });
|
|
491
|
-
// Write files
|
|
492
|
-
fs.writeFileSync(path.join(srcDir, 'main.cpp'), MAIN_CPP.replace('APP_NAME', name));
|
|
493
|
-
fs.writeFileSync(path.join(srcDir, 'AppState.h'), APPSTATE_H);
|
|
494
|
-
fs.writeFileSync(path.join(srcDir, 'App.tsx'), APP_TSX);
|
|
495
|
-
fs.writeFileSync(path.join(srcDir, 'imx.d.ts'), IMX_DTS);
|
|
496
|
-
fs.writeFileSync(path.join(projectDir, 'tsconfig.json'), TSCONFIG);
|
|
497
|
-
fs.writeFileSync(path.join(projectDir, 'CMakeLists.txt'), cmakeTemplate(name, 'https://github.com/bgocumlu/imx.git'));
|
|
498
|
-
fs.writeFileSync(path.join(projectDir, '.gitignore'), GITIGNORE);
|
|
499
|
-
console.log(`imxc: initialized project "${name}"`);
|
|
500
|
-
console.log('');
|
|
501
|
-
console.log(' Created:');
|
|
502
|
-
console.log(` src/main.cpp — app shell (GLFW + OpenGL + ImGui)`);
|
|
503
|
-
console.log(` src/AppState.h — C++ state struct (bound to TSX props)`);
|
|
504
|
-
console.log(` src/App.tsx — your root component`);
|
|
505
|
-
console.log(` src/imx.d.ts — type definitions for IDE support`);
|
|
506
|
-
console.log(` tsconfig.json — TypeScript config`);
|
|
507
|
-
console.log(` CMakeLists.txt — build config with FetchContent`);
|
|
508
|
-
console.log(` .gitignore — ignores build/, node_modules/, *.ini`);
|
|
509
|
-
console.log(` public/ — static assets (copied to exe directory)`);
|
|
510
|
-
console.log('');
|
|
511
|
-
console.log(' Next steps:');
|
|
512
|
-
console.log(` cmake -B build`);
|
|
513
|
-
console.log(` cmake --build build`);
|
|
101
|
+
entry.generate(projectDir, name);
|
|
514
102
|
}
|