@gtkx/cli 0.18.8 → 0.19.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.
- package/dist/create.js +1 -1
- package/dist/vite-plugin-gtkx-assets.d.ts +14 -5
- package/dist/vite-plugin-gtkx-assets.d.ts.map +1 -1
- package/dist/vite-plugin-gtkx-assets.js +37 -6
- package/dist/vite-plugin-gtkx-assets.js.map +1 -1
- package/env.d.ts +11 -0
- package/package.json +11 -9
- package/src/create.ts +1 -1
- package/src/vite-plugin-gtkx-assets.ts +43 -6
- package/templates/claude/EXAMPLES.md.ejs +3 -3
- package/templates/claude/WIDGETS.md.ejs +7 -7
- package/templates/package.json.ejs +1 -0
- package/templates/src/gtkx-env.d.ts.ejs +1 -0
- package/templates/src/vite-env.d.ts.ejs +0 -1
package/dist/create.js
CHANGED
|
@@ -126,7 +126,7 @@ const scaffoldProject = (projectPath, resolved) => {
|
|
|
126
126
|
writeFileSync(join(projectPath, "src", "app.tsx"), renderFile("src/app.tsx.ejs", context));
|
|
127
127
|
writeFileSync(join(projectPath, "src", "dev.tsx"), renderFile("src/dev.tsx.ejs", context));
|
|
128
128
|
writeFileSync(join(projectPath, "src", "index.tsx"), renderFile("src/index.tsx.ejs", context));
|
|
129
|
-
writeFileSync(join(projectPath, "src", "
|
|
129
|
+
writeFileSync(join(projectPath, "src", "gtkx-env.d.ts"), renderFile("src/gtkx-env.d.ts.ejs", context));
|
|
130
130
|
writeFileSync(join(projectPath, ".gitignore"), renderFile("gitignore.ejs", context));
|
|
131
131
|
if (claudeSkills) {
|
|
132
132
|
const skillsDir = join(projectPath, ".claude", "skills", "developing-gtkx-apps");
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
2
|
/**
|
|
3
|
-
* Vite plugin that resolves static asset imports to filesystem paths
|
|
3
|
+
* Vite plugin that resolves static asset imports to filesystem paths
|
|
4
|
+
* and handles CSS imports for GTK applications.
|
|
4
5
|
*
|
|
5
|
-
* In dev mode, asset imports resolve to the absolute
|
|
6
|
-
* In build mode, Vite's built-in asset pipeline handles
|
|
7
|
-
* hashing; the `renderBuiltUrl` config in the builder
|
|
8
|
-
* URL to a filesystem path via `import.meta.url`.
|
|
6
|
+
* **Non-CSS assets:** In dev mode, asset imports resolve to the absolute
|
|
7
|
+
* source file path. In build mode, Vite's built-in asset pipeline handles
|
|
8
|
+
* emission and hashing; the `renderBuiltUrl` config in the builder
|
|
9
|
+
* converts the URL to a filesystem path via `import.meta.url`.
|
|
10
|
+
*
|
|
11
|
+
* **CSS imports (`import "./style.css"`):** Transformed into a module that
|
|
12
|
+
* calls `injectGlobal` from `@gtkx/css` with the file's contents, injecting
|
|
13
|
+
* the styles into the GTK CSS provider at runtime.
|
|
14
|
+
*
|
|
15
|
+
* **CSS URL imports (`import path from "./style.css?url"`):** Handled by
|
|
16
|
+
* Vite's built-in `?url` mechanism, which emits the file as an asset and
|
|
17
|
+
* resolves it to a filesystem path via `renderBuiltUrl`.
|
|
9
18
|
*/
|
|
10
19
|
export declare function gtkxAssets(): Plugin;
|
|
11
20
|
//# sourceMappingURL=vite-plugin-gtkx-assets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin-gtkx-assets.d.ts","sourceRoot":"","sources":["../src/vite-plugin-gtkx-assets.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vite-plugin-gtkx-assets.d.ts","sourceRoot":"","sources":["../src/vite-plugin-gtkx-assets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAMnC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,IAAI,MAAM,CA4CnC"}
|
|
@@ -1,21 +1,52 @@
|
|
|
1
|
-
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
const ASSET_RE = /\.(png|jpe?g|gif|svg|webp|webm|mp4|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf|ico|avif|data)$/i;
|
|
3
|
+
const CSS_RE = /\.css$/i;
|
|
4
|
+
const VIRTUAL_PREFIX = "\0gtkx:";
|
|
2
5
|
/**
|
|
3
|
-
* Vite plugin that resolves static asset imports to filesystem paths
|
|
6
|
+
* Vite plugin that resolves static asset imports to filesystem paths
|
|
7
|
+
* and handles CSS imports for GTK applications.
|
|
4
8
|
*
|
|
5
|
-
* In dev mode, asset imports resolve to the absolute
|
|
6
|
-
* In build mode, Vite's built-in asset pipeline handles
|
|
7
|
-
* hashing; the `renderBuiltUrl` config in the builder
|
|
8
|
-
* URL to a filesystem path via `import.meta.url`.
|
|
9
|
+
* **Non-CSS assets:** In dev mode, asset imports resolve to the absolute
|
|
10
|
+
* source file path. In build mode, Vite's built-in asset pipeline handles
|
|
11
|
+
* emission and hashing; the `renderBuiltUrl` config in the builder
|
|
12
|
+
* converts the URL to a filesystem path via `import.meta.url`.
|
|
13
|
+
*
|
|
14
|
+
* **CSS imports (`import "./style.css"`):** Transformed into a module that
|
|
15
|
+
* calls `injectGlobal` from `@gtkx/css` with the file's contents, injecting
|
|
16
|
+
* the styles into the GTK CSS provider at runtime.
|
|
17
|
+
*
|
|
18
|
+
* **CSS URL imports (`import path from "./style.css?url"`):** Handled by
|
|
19
|
+
* Vite's built-in `?url` mechanism, which emits the file as an asset and
|
|
20
|
+
* resolves it to a filesystem path via `renderBuiltUrl`.
|
|
9
21
|
*/
|
|
10
22
|
export function gtkxAssets() {
|
|
11
23
|
let isBuild = false;
|
|
12
24
|
return {
|
|
13
25
|
name: "gtkx:assets",
|
|
14
26
|
enforce: "pre",
|
|
27
|
+
config() {
|
|
28
|
+
return {
|
|
29
|
+
assetsInclude: [ASSET_RE],
|
|
30
|
+
};
|
|
31
|
+
},
|
|
15
32
|
configResolved(config) {
|
|
16
33
|
isBuild = config.command === "build";
|
|
17
34
|
},
|
|
35
|
+
async resolveId(source, importer, options) {
|
|
36
|
+
if (!CSS_RE.test(source)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const resolved = await this.resolve(source, importer, { ...options, skipSelf: true });
|
|
40
|
+
if (!resolved || resolved.external)
|
|
41
|
+
return;
|
|
42
|
+
return `${VIRTUAL_PREFIX + resolved.id}?inject`;
|
|
43
|
+
},
|
|
18
44
|
load(id) {
|
|
45
|
+
if (id.startsWith(VIRTUAL_PREFIX) && id.endsWith("?inject")) {
|
|
46
|
+
const filePath = id.slice(VIRTUAL_PREFIX.length, -"?inject".length);
|
|
47
|
+
const content = readFileSync(filePath, "utf-8");
|
|
48
|
+
return [`import { injectGlobal } from "@gtkx/css";`, `injectGlobal(${JSON.stringify(content)});`].join("\n");
|
|
49
|
+
}
|
|
19
50
|
if (isBuild || !ASSET_RE.test(id)) {
|
|
20
51
|
return;
|
|
21
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin-gtkx-assets.js","sourceRoot":"","sources":["../src/vite-plugin-gtkx-assets.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vite-plugin-gtkx-assets.js","sourceRoot":"","sources":["../src/vite-plugin-gtkx-assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,MAAM,QAAQ,GAAG,6FAA6F,CAAC;AAC/G,MAAM,MAAM,GAAG,SAAS,CAAC;AACzB,MAAM,cAAc,GAAG,SAAS,CAAC;AAEjC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,UAAU;IACtB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,OAAO;QACH,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,KAAK;QAEd,MAAM;YACF,OAAO;gBACH,aAAa,EAAE,CAAC,QAAQ,CAAC;aAC5B,CAAC;QACN,CAAC;QAED,cAAc,CAAC,MAAM;YACjB,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC;QACzC,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO;YACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvB,OAAO;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACtF,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ;gBAAE,OAAO;YAE3C,OAAO,GAAG,cAAc,GAAG,QAAQ,CAAC,EAAE,SAAS,CAAC;QACpD,CAAC;QAED,IAAI,CAAC,EAAE;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1D,MAAM,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBACpE,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAChD,OAAO,CAAC,2CAA2C,EAAE,gBAAgB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAClG,IAAI,CACP,CAAC;YACN,CAAC;YAED,IAAI,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBAChC,OAAO;YACX,CAAC;YAED,OAAO,kBAAkB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC;QACnD,CAAC;KACJ,CAAC;AACN,CAAC"}
|
package/env.d.ts
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "CLI for GTKX - create and develop GTK4 React applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtkx",
|
|
@@ -45,7 +45,8 @@
|
|
|
45
45
|
"./refresh-runtime": {
|
|
46
46
|
"types": "./dist/refresh-runtime.d.ts",
|
|
47
47
|
"default": "./dist/refresh-runtime.js"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"./env": "./env.d.ts"
|
|
49
50
|
},
|
|
50
51
|
"bin": {
|
|
51
52
|
"gtkx": "bin/gtkx.js"
|
|
@@ -54,29 +55,30 @@
|
|
|
54
55
|
"files": [
|
|
55
56
|
"bin",
|
|
56
57
|
"dist",
|
|
58
|
+
"env.d.ts",
|
|
57
59
|
"src",
|
|
58
60
|
"templates"
|
|
59
61
|
],
|
|
60
62
|
"dependencies": {
|
|
61
|
-
"@clack/prompts": "^1.0.
|
|
63
|
+
"@clack/prompts": "^1.0.1",
|
|
62
64
|
"@swc/core": "^1.15.11",
|
|
63
|
-
"citty": "^0.2.
|
|
65
|
+
"citty": "^0.2.1",
|
|
64
66
|
"ejs": "^4.0.1",
|
|
65
67
|
"react-refresh": "^0.18.0",
|
|
66
68
|
"vite": "^7.3.1",
|
|
67
|
-
"@gtkx/ffi": "0.
|
|
68
|
-
"@gtkx/react": "0.
|
|
69
|
-
"@gtkx/mcp": "0.
|
|
69
|
+
"@gtkx/ffi": "0.19.0",
|
|
70
|
+
"@gtkx/react": "0.19.0",
|
|
71
|
+
"@gtkx/mcp": "0.19.0"
|
|
70
72
|
},
|
|
71
73
|
"devDependencies": {
|
|
72
74
|
"@types/ejs": "^3.1.5",
|
|
73
75
|
"@types/react-refresh": "^0.14.7",
|
|
74
76
|
"memfs": "^4.56.10",
|
|
75
|
-
"@gtkx/testing": "0.
|
|
77
|
+
"@gtkx/testing": "0.19.0"
|
|
76
78
|
},
|
|
77
79
|
"peerDependencies": {
|
|
78
80
|
"react": "^19",
|
|
79
|
-
"@gtkx/testing": "0.
|
|
81
|
+
"@gtkx/testing": "0.19.0"
|
|
80
82
|
},
|
|
81
83
|
"peerDependenciesMeta": {
|
|
82
84
|
"@gtkx/testing": {
|
package/src/create.ts
CHANGED
|
@@ -196,7 +196,7 @@ const scaffoldProject = (projectPath: string, resolved: ResolvedOptions): void =
|
|
|
196
196
|
writeFileSync(join(projectPath, "src", "app.tsx"), renderFile("src/app.tsx.ejs", context));
|
|
197
197
|
writeFileSync(join(projectPath, "src", "dev.tsx"), renderFile("src/dev.tsx.ejs", context));
|
|
198
198
|
writeFileSync(join(projectPath, "src", "index.tsx"), renderFile("src/index.tsx.ejs", context));
|
|
199
|
-
writeFileSync(join(projectPath, "src", "
|
|
199
|
+
writeFileSync(join(projectPath, "src", "gtkx-env.d.ts"), renderFile("src/gtkx-env.d.ts.ejs", context));
|
|
200
200
|
writeFileSync(join(projectPath, ".gitignore"), renderFile("gitignore.ejs", context));
|
|
201
201
|
|
|
202
202
|
if (claudeSkills) {
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
1
2
|
import type { Plugin } from "vite";
|
|
2
3
|
|
|
3
|
-
const ASSET_RE = /\.(png|jpe?g|gif|svg|webp|webm|mp4|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf|ico|avif)$/i;
|
|
4
|
+
const ASSET_RE = /\.(png|jpe?g|gif|svg|webp|webm|mp4|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf|ico|avif|data)$/i;
|
|
5
|
+
const CSS_RE = /\.css$/i;
|
|
6
|
+
const VIRTUAL_PREFIX = "\0gtkx:";
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
|
-
* Vite plugin that resolves static asset imports to filesystem paths
|
|
9
|
+
* Vite plugin that resolves static asset imports to filesystem paths
|
|
10
|
+
* and handles CSS imports for GTK applications.
|
|
7
11
|
*
|
|
8
|
-
* In dev mode, asset imports resolve to the absolute
|
|
9
|
-
* In build mode, Vite's built-in asset pipeline handles
|
|
10
|
-
* hashing; the `renderBuiltUrl` config in the builder
|
|
11
|
-
* URL to a filesystem path via `import.meta.url`.
|
|
12
|
+
* **Non-CSS assets:** In dev mode, asset imports resolve to the absolute
|
|
13
|
+
* source file path. In build mode, Vite's built-in asset pipeline handles
|
|
14
|
+
* emission and hashing; the `renderBuiltUrl` config in the builder
|
|
15
|
+
* converts the URL to a filesystem path via `import.meta.url`.
|
|
16
|
+
*
|
|
17
|
+
* **CSS imports (`import "./style.css"`):** Transformed into a module that
|
|
18
|
+
* calls `injectGlobal` from `@gtkx/css` with the file's contents, injecting
|
|
19
|
+
* the styles into the GTK CSS provider at runtime.
|
|
20
|
+
*
|
|
21
|
+
* **CSS URL imports (`import path from "./style.css?url"`):** Handled by
|
|
22
|
+
* Vite's built-in `?url` mechanism, which emits the file as an asset and
|
|
23
|
+
* resolves it to a filesystem path via `renderBuiltUrl`.
|
|
12
24
|
*/
|
|
13
25
|
export function gtkxAssets(): Plugin {
|
|
14
26
|
let isBuild = false;
|
|
@@ -17,11 +29,36 @@ export function gtkxAssets(): Plugin {
|
|
|
17
29
|
name: "gtkx:assets",
|
|
18
30
|
enforce: "pre",
|
|
19
31
|
|
|
32
|
+
config() {
|
|
33
|
+
return {
|
|
34
|
+
assetsInclude: [ASSET_RE],
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
|
|
20
38
|
configResolved(config) {
|
|
21
39
|
isBuild = config.command === "build";
|
|
22
40
|
},
|
|
23
41
|
|
|
42
|
+
async resolveId(source, importer, options) {
|
|
43
|
+
if (!CSS_RE.test(source)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const resolved = await this.resolve(source, importer, { ...options, skipSelf: true });
|
|
48
|
+
if (!resolved || resolved.external) return;
|
|
49
|
+
|
|
50
|
+
return `${VIRTUAL_PREFIX + resolved.id}?inject`;
|
|
51
|
+
},
|
|
52
|
+
|
|
24
53
|
load(id) {
|
|
54
|
+
if (id.startsWith(VIRTUAL_PREFIX) && id.endsWith("?inject")) {
|
|
55
|
+
const filePath = id.slice(VIRTUAL_PREFIX.length, -"?inject".length);
|
|
56
|
+
const content = readFileSync(filePath, "utf-8");
|
|
57
|
+
return [`import { injectGlobal } from "@gtkx/css";`, `injectGlobal(${JSON.stringify(content)});`].join(
|
|
58
|
+
"\n",
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
25
62
|
if (isBuild || !ASSET_RE.test(id)) {
|
|
26
63
|
return;
|
|
27
64
|
}
|
|
@@ -340,9 +340,9 @@ const FileTable = () => {
|
|
|
340
340
|
return (
|
|
341
341
|
<GtkScrolledWindow vexpand cssClasses={["card"]}>
|
|
342
342
|
<GtkColumnView estimatedRowHeight={48} sortColumn={sortColumn} sortOrder={sortOrder} onSortChanged={handleSort}>
|
|
343
|
-
<x.ColumnViewColumn
|
|
344
|
-
<x.ColumnViewColumn
|
|
345
|
-
<x.ColumnViewColumn
|
|
343
|
+
<x.ColumnViewColumn title="Name" id="name" expand sortable renderCell={(f: FileItem | null) => <GtkLabel label={f?.name ?? ""} />} />
|
|
344
|
+
<x.ColumnViewColumn title="Size" id="size" fixedWidth={100} sortable renderCell={(f: FileItem | null) => <GtkLabel label={`${f?.size ?? 0} KB`} />} />
|
|
345
|
+
<x.ColumnViewColumn title="Modified" id="modified" fixedWidth={120} sortable renderCell={(f: FileItem | null) => <GtkLabel label={f?.modified ?? ""} />} />
|
|
346
346
|
{sortedFiles.map((file) => (
|
|
347
347
|
<x.ListItem key={file.id} id={file.id} value={file} />
|
|
348
348
|
))}
|
|
@@ -172,19 +172,19 @@ Table with sortable columns.
|
|
|
172
172
|
|
|
173
173
|
```tsx
|
|
174
174
|
<GtkColumnView estimatedRowHeight={48} sortColumn="name" sortOrder={Gtk.SortType.ASCENDING} onSortChanged={handleSort}>
|
|
175
|
-
<x.ColumnViewColumn
|
|
175
|
+
<x.ColumnViewColumn
|
|
176
176
|
title="Name"
|
|
177
177
|
id="name"
|
|
178
178
|
expand
|
|
179
179
|
resizable
|
|
180
180
|
sortable
|
|
181
|
-
renderCell={(item) => <GtkLabel label={item?.name ?? ""} />}
|
|
181
|
+
renderCell={(item: Item | null) => <GtkLabel label={item?.name ?? ""} />}
|
|
182
182
|
/>
|
|
183
|
-
<x.ColumnViewColumn
|
|
183
|
+
<x.ColumnViewColumn
|
|
184
184
|
title="Size"
|
|
185
185
|
id="size"
|
|
186
186
|
fixedWidth={100}
|
|
187
|
-
renderCell={(item) => <GtkLabel label={`${item?.size ?? 0} KB`} />}
|
|
187
|
+
renderCell={(item: Item | null) => <GtkLabel label={`${item?.size ?? 0} KB`} />}
|
|
188
188
|
/>
|
|
189
189
|
{items.map(item => <x.ListItem key={item.id} id={item.id} value={item} />)}
|
|
190
190
|
</GtkColumnView>
|
|
@@ -799,14 +799,14 @@ Text content is provided as direct children. Use `x.TextTag` for formatting and
|
|
|
799
799
|
|
|
800
800
|
## Keyboard Shortcuts
|
|
801
801
|
|
|
802
|
-
Attach shortcuts with
|
|
802
|
+
Attach shortcuts with `<GtkShortcutController>` and `x.Shortcut`:
|
|
803
803
|
|
|
804
804
|
```tsx
|
|
805
805
|
<GtkBox orientation={Gtk.Orientation.VERTICAL} spacing={12} focusable>
|
|
806
|
-
<
|
|
806
|
+
<GtkShortcutController scope={Gtk.ShortcutScope.LOCAL}>
|
|
807
807
|
<x.Shortcut trigger="<Control>equal" onActivate={() => setCount((c) => c + 1)} />
|
|
808
808
|
<x.Shortcut trigger="<Control>minus" onActivate={() => setCount((c) => c - 1)} />
|
|
809
|
-
</
|
|
809
|
+
</GtkShortcutController>
|
|
810
810
|
<GtkLabel label={`Count: ${count}`} />
|
|
811
811
|
</GtkBox>
|
|
812
812
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="@gtkx/cli/env" />
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="vite/client" />
|