create-rezi 0.1.0-alpha.2 → 0.1.0-alpha.21

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.
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=scaffold.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scaffold.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/scaffold.test.ts"],"names":[],"mappings":""}
@@ -1,29 +0,0 @@
1
- import { mkdtemp, readFile } from "node:fs/promises";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import { assert, test } from "@rezi-ui/testkit";
5
- import { createProject, normalizeTemplateName, toValidPackageName } from "../scaffold.js";
6
- test("normalizeTemplateName accepts friendly aliases", () => {
7
- assert.equal(normalizeTemplateName("form app"), "form-app");
8
- assert.equal(normalizeTemplateName("file-browser"), "file-browser");
9
- assert.equal(normalizeTemplateName("streaming"), "streaming-viewer");
10
- });
11
- test("createProject scaffolds a dashboard project with substitutions", async () => {
12
- const root = await mkdtemp(join(tmpdir(), "rezi-create-"));
13
- const targetDir = join(root, "my-app");
14
- const displayName = "My Rezi App";
15
- const packageName = toValidPackageName("my-rezi-app");
16
- await createProject({
17
- targetDir,
18
- templateKey: "dashboard",
19
- packageName,
20
- displayName,
21
- });
22
- const pkgRaw = await readFile(join(targetDir, "package.json"), "utf8");
23
- const pkg = JSON.parse(pkgRaw);
24
- assert.equal(pkg.name, packageName);
25
- const main = await readFile(join(targetDir, "src", "main.ts"), "utf8");
26
- assert.ok(main.includes(displayName));
27
- assert.ok(!main.includes("__APP_NAME__"));
28
- });
29
- //# sourceMappingURL=scaffold.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scaffold.test.js","sourceRoot":"","sources":["../../src/__tests__/scaffold.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAE1F,IAAI,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC1D,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC;IAC5D,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC,CAAC;IACpE,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;IAChF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvC,MAAM,WAAW,GAAG,aAAa,CAAC;IAClC,MAAM,WAAW,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAEtD,MAAM,aAAa,CAAC;QAClB,SAAS;QACT,WAAW,EAAE,WAAW;QACxB,WAAW;QACX,WAAW;KACZ,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;IACvE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAqB,CAAC;IACnD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAEpC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;IACvE,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC"}
@@ -1,18 +0,0 @@
1
- # __APP_NAME__
2
-
3
- Scaffolded with `npm create rezi` using the **__TEMPLATE_LABEL__** template.
4
-
5
- ## Quickstart
6
-
7
- ```bash
8
- npm install
9
- npm start
10
- ```
11
-
12
- ## Keybindings
13
-
14
- - `up` / `down` or `j` / `k`: Move selection
15
- - `enter`: Open directory / preview file
16
- - `backspace`: Go up
17
- - `h`: Toggle hidden files
18
- - `q`: Quit
@@ -1,258 +0,0 @@
1
- import { createApp, rgb, ui } from "@rezi-ui/core";
2
- import { createNodeBackend } from "@rezi-ui/node";
3
-
4
- type EntryType = "dir" | "file";
5
-
6
- type Entry = {
7
- name: string;
8
- type: EntryType;
9
- size: string;
10
- modified: string;
11
- preview: string;
12
- };
13
-
14
- type Tree = Record<string, Entry[]>;
15
-
16
- const tree: Tree = {
17
- "/": [
18
- { name: "src", type: "dir", size: "-", modified: "2026-02-10", preview: "" },
19
- { name: "docs", type: "dir", size: "-", modified: "2026-02-08", preview: "" },
20
- {
21
- name: "package.json",
22
- type: "file",
23
- size: "2 KB",
24
- modified: "2026-02-07",
25
- preview: '{\n "name": "__APP_NAME__"\n}',
26
- },
27
- { name: ".env", type: "file", size: "1 KB", modified: "2026-02-05", preview: "API_KEY=***" },
28
- ],
29
- "/src": [
30
- {
31
- name: "main.ts",
32
- type: "file",
33
- size: "4 KB",
34
- modified: "2026-02-10",
35
- preview: "import { createApp } from '@rezi-ui/core'",
36
- },
37
- { name: "components", type: "dir", size: "-", modified: "2026-02-09", preview: "" },
38
- { name: "styles", type: "dir", size: "-", modified: "2026-02-09", preview: "" },
39
- ],
40
- "/src/components": [
41
- {
42
- name: "Panel.ts",
43
- type: "file",
44
- size: "1 KB",
45
- modified: "2026-02-09",
46
- preview: "export function Panel() {}",
47
- },
48
- {
49
- name: "StatusBar.ts",
50
- type: "file",
51
- size: "1 KB",
52
- modified: "2026-02-09",
53
- preview: "export function StatusBar() {}",
54
- },
55
- ],
56
- "/docs": [
57
- {
58
- name: "overview.md",
59
- type: "file",
60
- size: "3 KB",
61
- modified: "2026-02-08",
62
- preview: "# Overview",
63
- },
64
- { name: "usage.md", type: "file", size: "2 KB", modified: "2026-02-08", preview: "# Usage" },
65
- ],
66
- "/src/styles": [
67
- {
68
- name: "tokens.ts",
69
- type: "file",
70
- size: "2 KB",
71
- modified: "2026-02-08",
72
- preview: "export const colors = {}",
73
- },
74
- ],
75
- };
76
-
77
- const colors = {
78
- accent: rgb(120, 200, 255),
79
- muted: rgb(140, 150, 170),
80
- panel: rgb(18, 22, 34),
81
- panelAlt: rgb(22, 28, 44),
82
- ink: rgb(10, 14, 24),
83
- };
84
-
85
- type State = {
86
- path: string;
87
- selected: number;
88
- showHidden: boolean;
89
- opened: string | null;
90
- };
91
-
92
- const app = createApp<State>({
93
- backend: createNodeBackend(),
94
- initialState: {
95
- path: "/",
96
- selected: 0,
97
- showHidden: false,
98
- opened: null,
99
- },
100
- });
101
-
102
- function clamp(value: number, min: number, max: number) {
103
- return Math.max(min, Math.min(max, value));
104
- }
105
-
106
- function joinPath(base: string, name: string): string {
107
- if (base === "/") return `/${name}`;
108
- return `${base}/${name}`;
109
- }
110
-
111
- function parentPath(path: string): string {
112
- if (path === "/") return "/";
113
- const parts = path.split("/").filter(Boolean);
114
- parts.pop();
115
- return `/${parts.join("/")}` || "/";
116
- }
117
-
118
- function listEntries(state: State): Entry[] {
119
- const entries = tree[state.path] ?? [];
120
- if (state.showHidden) return entries;
121
- return entries.filter((entry) => !entry.name.startsWith("."));
122
- }
123
-
124
- function panel(title: string, children: ReturnType<typeof ui.column>[], flex = 1) {
125
- return ui.box(
126
- { title, flex, border: "rounded", px: 1, py: 0, style: { bg: colors.panel, fg: colors.muted } },
127
- children,
128
- );
129
- }
130
-
131
- app.view((state) => {
132
- const entries = listEntries(state);
133
- const selected = entries[state.selected];
134
- const preview = selected?.preview || "Select a file to preview.";
135
-
136
- return ui.column({ flex: 1, p: 1, gap: 1, items: "stretch" }, [
137
- ui.row({ justify: "between", items: "center" }, [
138
- ui.text("__APP_NAME__", { fg: colors.accent, bold: true }),
139
- ui.text(`Path: ${state.path}`, { fg: colors.muted }),
140
- ]),
141
-
142
- ui.row({ flex: 1, gap: 1, items: "stretch" }, [
143
- panel(
144
- "Files",
145
- [
146
- ui.column(
147
- { gap: 0 },
148
- entries.map((entry, index) => {
149
- const active = index === state.selected;
150
- const prefix = active ? ">" : " ";
151
- const marker = entry.type === "dir" ? "[D]" : "[F]";
152
- return ui.text(`${prefix} ${marker} ${entry.name}`, {
153
- key: entry.name,
154
- style: {
155
- fg: active ? colors.accent : colors.muted,
156
- bold: active,
157
- },
158
- });
159
- }),
160
- ),
161
- ],
162
- 1,
163
- ),
164
-
165
- panel(
166
- "Details",
167
- [
168
- ui.column({ gap: 1 }, [
169
- ui.text(selected ? selected.name : "-", { fg: colors.accent, bold: true }),
170
- ui.text(`Type: ${selected?.type ?? "-"}`),
171
- ui.text(`Size: ${selected?.size ?? "-"}`),
172
- ui.text(`Modified: ${selected?.modified ?? "-"}`),
173
- ui.divider({ char: "-" }),
174
- ui.text("Preview", { fg: colors.muted }),
175
- ui.text(preview),
176
- ]),
177
- ],
178
- 2,
179
- ),
180
-
181
- panel(
182
- "Pinned",
183
- [
184
- ui.column({ gap: 1 }, [
185
- ui.text("Last opened", { fg: colors.muted }),
186
- ui.text(state.opened ?? "-"),
187
- ui.text(""),
188
- ui.text("Hidden files"),
189
- ui.text(state.showHidden ? "Visible" : "Hidden"),
190
- ]),
191
- ],
192
- 1,
193
- ),
194
- ]),
195
-
196
- ui.box({ px: 1, py: 0, style: { bg: colors.ink, fg: colors.muted } }, [
197
- ui.row({ justify: "between", items: "center" }, [
198
- ui.text("File browser ready"),
199
- ui.row({ gap: 1 }, [
200
- ui.kbd("up"),
201
- ui.text("Move"),
202
- ui.kbd("enter"),
203
- ui.text("Open"),
204
- ui.kbd("backspace"),
205
- ui.text("Up"),
206
- ui.kbd("h"),
207
- ui.text("Hidden"),
208
- ui.kbd("q"),
209
- ui.text("Quit"),
210
- ]),
211
- ]),
212
- ]),
213
- ]);
214
- });
215
-
216
- app.keys({
217
- q: () => app.stop(),
218
- "ctrl+c": () => app.stop(),
219
- up: () =>
220
- app.update((s) => {
221
- const entries = listEntries(s);
222
- return { ...s, selected: clamp(s.selected - 1, 0, Math.max(0, entries.length - 1)) };
223
- }),
224
- down: () =>
225
- app.update((s) => {
226
- const entries = listEntries(s);
227
- return { ...s, selected: clamp(s.selected + 1, 0, Math.max(0, entries.length - 1)) };
228
- }),
229
- k: () =>
230
- app.update((s) => {
231
- const entries = listEntries(s);
232
- return { ...s, selected: clamp(s.selected - 1, 0, Math.max(0, entries.length - 1)) };
233
- }),
234
- j: () =>
235
- app.update((s) => {
236
- const entries = listEntries(s);
237
- return { ...s, selected: clamp(s.selected + 1, 0, Math.max(0, entries.length - 1)) };
238
- }),
239
- h: () => app.update((s) => ({ ...s, showHidden: !s.showHidden, selected: 0 })),
240
- backspace: () =>
241
- app.update((s) => ({
242
- ...s,
243
- path: parentPath(s.path),
244
- selected: 0,
245
- })),
246
- enter: () =>
247
- app.update((s) => {
248
- const entries = listEntries(s);
249
- const entry = entries[s.selected];
250
- if (!entry) return s;
251
- if (entry.type === "dir") {
252
- return { ...s, path: joinPath(s.path, entry.name), selected: 0 };
253
- }
254
- return { ...s, opened: joinPath(s.path, entry.name) };
255
- }),
256
- });
257
-
258
- await app.start();
@@ -1,18 +0,0 @@
1
- # __APP_NAME__
2
-
3
- Scaffolded with `npm create rezi` using the **__TEMPLATE_LABEL__** template.
4
-
5
- ## Quickstart
6
-
7
- ```bash
8
- npm install
9
- npm start
10
- ```
11
-
12
- ## Keybindings
13
-
14
- - `tab`: Move focus between fields
15
- - `ctrl+s`: Save
16
- - `ctrl+r`: Reset form
17
- - `ctrl+up` / `ctrl+down`: Switch section
18
- - `q`: Quit
@@ -1,23 +0,0 @@
1
- {
2
- "name": "__PACKAGE_NAME__",
3
- "version": "0.1.0",
4
- "private": true,
5
- "type": "module",
6
- "scripts": {
7
- "start": "tsx src/main.ts",
8
- "dev": "tsx watch src/main.ts",
9
- "typecheck": "tsc --noEmit"
10
- },
11
- "dependencies": {
12
- "@rezi-ui/core": "^0.1.0-alpha.0",
13
- "@rezi-ui/node": "^0.1.0-alpha.0"
14
- },
15
- "devDependencies": {
16
- "@types/node": "^22.13.1",
17
- "tsx": "^4.20.0",
18
- "typescript": "^5.6.3"
19
- },
20
- "engines": {
21
- "node": ">=18"
22
- }
23
- }
@@ -1,222 +0,0 @@
1
- import { createApp, rgb, ui } from "@rezi-ui/core";
2
- import { createNodeBackend } from "@rezi-ui/node";
3
-
4
- type Plan = "starter" | "growth" | "enterprise";
5
-
6
- type State = {
7
- section: number;
8
- name: string;
9
- email: string;
10
- company: string;
11
- plan: Plan;
12
- seats: string;
13
- newsletter: boolean;
14
- notes: string;
15
- status: string;
16
- };
17
-
18
- const sections = ["Profile", "Plan", "Review"] as const;
19
-
20
- const initialState: State = {
21
- section: 0,
22
- name: "",
23
- email: "",
24
- company: "",
25
- plan: "growth",
26
- seats: "5",
27
- newsletter: true,
28
- notes: "",
29
- status: "Draft",
30
- };
31
-
32
- const app = createApp<State>({
33
- backend: createNodeBackend(),
34
- initialState,
35
- });
36
-
37
- const colors = {
38
- accent: rgb(116, 200, 255),
39
- muted: rgb(140, 150, 170),
40
- panel: rgb(18, 22, 34),
41
- panelAlt: rgb(22, 28, 44),
42
- ok: rgb(130, 220, 170),
43
- ink: rgb(10, 14, 24),
44
- };
45
-
46
- function clamp(value: number, min: number, max: number) {
47
- return Math.max(min, Math.min(max, value));
48
- }
49
-
50
- function panel(title: string, children: ReturnType<typeof ui.column>[], flex = 1) {
51
- return ui.box(
52
- {
53
- title,
54
- flex,
55
- border: "rounded",
56
- px: 1,
57
- py: 0,
58
- style: { bg: colors.panel, fg: colors.muted },
59
- },
60
- children,
61
- );
62
- }
63
-
64
- app.view((state) => {
65
- return ui.column({ flex: 1, p: 1, gap: 1, items: "stretch" }, [
66
- ui.row({ justify: "between", items: "center" }, [
67
- ui.text("__APP_NAME__", { fg: colors.accent, bold: true }),
68
- ui.text(`Status: ${state.status}`, { fg: colors.ok, bold: true }),
69
- ]),
70
-
71
- ui.row({ flex: 1, gap: 1, items: "stretch" }, [
72
- panel(
73
- "Sections",
74
- [
75
- ui.column(
76
- { gap: 0 },
77
- sections.map((label, index) => {
78
- const active = index === state.section;
79
- return ui.text(`${active ? ">" : " "} ${label}`, {
80
- key: label,
81
- style: {
82
- fg: active ? colors.accent : colors.muted,
83
- bold: active,
84
- },
85
- });
86
- }),
87
- ),
88
- ],
89
- 1,
90
- ),
91
-
92
- panel(
93
- "Customer Details",
94
- [
95
- ui.column({ gap: 1 }, [
96
- ui.field({
97
- label: "Name",
98
- required: true,
99
- children: ui.input({
100
- id: "name",
101
- value: state.name,
102
- onInput: (value) => app.update((s) => ({ ...s, name: value })),
103
- }),
104
- }),
105
- ui.field({
106
- label: "Email",
107
- required: true,
108
- children: ui.input({
109
- id: "email",
110
- value: state.email,
111
- onInput: (value) => app.update((s) => ({ ...s, email: value })),
112
- }),
113
- }),
114
- ui.field({
115
- label: "Company",
116
- children: ui.input({
117
- id: "company",
118
- value: state.company,
119
- onInput: (value) => app.update((s) => ({ ...s, company: value })),
120
- }),
121
- }),
122
- ui.field({
123
- label: "Plan",
124
- children: ui.select({
125
- id: "plan",
126
- value: state.plan,
127
- options: [
128
- { value: "starter", label: "Starter" },
129
- { value: "growth", label: "Growth" },
130
- { value: "enterprise", label: "Enterprise" },
131
- ],
132
- onChange: (value) => app.update((s) => ({ ...s, plan: value as Plan })),
133
- }),
134
- }),
135
- ui.field({
136
- label: "Seats",
137
- children: ui.input({
138
- id: "seats",
139
- value: state.seats,
140
- onInput: (value) => app.update((s) => ({ ...s, seats: value })),
141
- }),
142
- }),
143
- ui.checkbox({
144
- id: "newsletter",
145
- label: "Subscribe to release notes",
146
- checked: state.newsletter,
147
- onChange: (checked) => app.update((s) => ({ ...s, newsletter: checked })),
148
- }),
149
- ]),
150
- ],
151
- 2,
152
- ),
153
-
154
- panel(
155
- "Preview",
156
- [
157
- ui.column({ gap: 1 }, [
158
- ui.text("Summary", { fg: colors.accent, bold: true }),
159
- ui.text(`Name: ${state.name || "-"}`),
160
- ui.text(`Email: ${state.email || "-"}`),
161
- ui.text(`Company: ${state.company || "-"}`),
162
- ui.text(`Plan: ${state.plan}`),
163
- ui.text(`Seats: ${state.seats || "-"}`),
164
- ui.text(`Newsletter: ${state.newsletter ? "Yes" : "No"}`),
165
- ui.divider({ char: "-" }),
166
- ui.text("Notes"),
167
- ui.text(state.notes || "Add internal notes in Review."),
168
- ui.button({
169
- id: "save",
170
- label: "Save draft",
171
- onPress: () =>
172
- app.update((s) => ({
173
- ...s,
174
- status: `Saved at ${new Date().toLocaleTimeString()}`,
175
- })),
176
- }),
177
- ]),
178
- ],
179
- 1,
180
- ),
181
- ]),
182
-
183
- ui.box({ px: 1, py: 0, style: { bg: colors.ink, fg: colors.muted } }, [
184
- ui.row({ justify: "between", items: "center" }, [
185
- ui.text("Form flow ready"),
186
- ui.row({ gap: 1 }, [
187
- ui.kbd("tab"),
188
- ui.text("Focus"),
189
- ui.kbd("ctrl+s"),
190
- ui.text("Save"),
191
- ui.kbd("ctrl+r"),
192
- ui.text("Reset"),
193
- ui.kbd("q"),
194
- ui.text("Quit"),
195
- ]),
196
- ]),
197
- ]),
198
- ]);
199
- });
200
-
201
- app.keys({
202
- q: () => app.stop(),
203
- "ctrl+c": () => app.stop(),
204
- "ctrl+s": () =>
205
- app.update((s) => ({
206
- ...s,
207
- status: `Saved at ${new Date().toLocaleTimeString()}`,
208
- })),
209
- "ctrl+r": () => app.update(() => ({ ...initialState })),
210
- "ctrl+up": () =>
211
- app.update((s) => ({
212
- ...s,
213
- section: clamp(s.section - 1, 0, sections.length - 1),
214
- })),
215
- "ctrl+down": () =>
216
- app.update((s) => ({
217
- ...s,
218
- section: clamp(s.section + 1, 0, sections.length - 1),
219
- })),
220
- });
221
-
222
- await app.start();
@@ -1,17 +0,0 @@
1
- # __APP_NAME__
2
-
3
- Scaffolded with `npm create rezi` using the **__TEMPLATE_LABEL__** template.
4
-
5
- ## Quickstart
6
-
7
- ```bash
8
- npm install
9
- npm start
10
- ```
11
-
12
- ## Keybindings
13
-
14
- - `up` / `down` or `j` / `k`: Switch stream
15
- - `space`: Toggle pause
16
- - `f`: Follow mode
17
- - `q`: Quit