@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 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", "vite-env.d.ts"), renderFile("src/vite-env.d.ts.ejs", context));
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 source file path.
6
- * In build mode, Vite's built-in asset pipeline handles emission and
7
- * hashing; the `renderBuiltUrl` config in the builder converts the
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":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC;;;;;;;GAOG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAmBnC"}
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
- const ASSET_RE = /\.(png|jpe?g|gif|svg|webp|webm|mp4|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf|ico|avif)$/i;
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 source file path.
6
- * In build mode, Vite's built-in asset pipeline handles emission and
7
- * hashing; the `renderBuiltUrl` config in the builder converts the
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":"AAEA,MAAM,QAAQ,GAAG,wFAAwF,CAAC;AAE1G;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU;IACtB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,OAAO;QACH,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,KAAK;QAEd,cAAc,CAAC,MAAM;YACjB,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC;QACzC,CAAC;QAED,IAAI,CAAC,EAAE;YACH,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"}
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
@@ -0,0 +1,11 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ declare module "*.css?url" {
4
+ const path: string;
5
+ export default path;
6
+ }
7
+
8
+ declare module "*.data" {
9
+ const path: string;
10
+ export default path;
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/cli",
3
- "version": "0.18.8",
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.0",
63
+ "@clack/prompts": "^1.0.1",
62
64
  "@swc/core": "^1.15.11",
63
- "citty": "^0.2.0",
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.18.8",
68
- "@gtkx/react": "0.18.8",
69
- "@gtkx/mcp": "0.18.8"
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.18.8"
77
+ "@gtkx/testing": "0.19.0"
76
78
  },
77
79
  "peerDependencies": {
78
80
  "react": "^19",
79
- "@gtkx/testing": "0.18.8"
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", "vite-env.d.ts"), renderFile("src/vite-env.d.ts.ejs", context));
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 source file path.
9
- * In build mode, Vite's built-in asset pipeline handles emission and
10
- * hashing; the `renderBuiltUrl` config in the builder converts the
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<FileItem> title="Name" id="name" expand sortable renderCell={(f) => <GtkLabel label={f?.name ?? ""} />} />
344
- <x.ColumnViewColumn<FileItem> title="Size" id="size" fixedWidth={100} sortable renderCell={(f) => <GtkLabel label={`${f?.size ?? 0} KB`} />} />
345
- <x.ColumnViewColumn<FileItem> title="Modified" id="modified" fixedWidth={120} sortable renderCell={(f) => <GtkLabel label={f?.modified ?? ""} />} />
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<Item>
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<Item>
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 `x.ShortcutController` and `x.Shortcut`:
802
+ Attach shortcuts with `<GtkShortcutController>` and `x.Shortcut`:
803
803
 
804
804
  ```tsx
805
805
  <GtkBox orientation={Gtk.Orientation.VERTICAL} spacing={12} focusable>
806
- <x.ShortcutController scope={Gtk.ShortcutScope.LOCAL}>
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
- </x.ShortcutController>
809
+ </GtkShortcutController>
810
810
  <GtkLabel label={`Count: ${count}`} />
811
811
  </GtkBox>
812
812
  ```
@@ -6,6 +6,7 @@
6
6
  "scripts": {
7
7
  "dev": "gtkx dev src/dev.tsx",
8
8
  "build": "gtkx build",
9
+ "typecheck": "tsc --noEmit",
9
10
  "start": "node dist/bundle.js"<% if (testing === 'vitest') { %>,
10
11
  "test": "vitest"<% } %>
11
12
  },
@@ -0,0 +1 @@
1
+ /// <reference types="@gtkx/cli/env" />
@@ -1 +0,0 @@
1
- /// <reference types="vite/client" />