react-native-gtkx 0.1.0-alpha.2 → 0.1.0-alpha.4

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 (105) hide show
  1. package/README.md +41 -8
  2. package/dist/animated/create-animated.js +1 -1
  3. package/dist/animated/create-animated.js.map +1 -1
  4. package/dist/animated/index.js +3 -3
  5. package/dist/animated/index.js.map +1 -1
  6. package/dist/apis/back-handler.d.ts +9 -0
  7. package/dist/apis/back-handler.js +30 -0
  8. package/dist/apis/back-handler.js.map +1 -0
  9. package/dist/apis/host.d.ts +7 -1
  10. package/dist/apis/host.gtkx.js +12 -1
  11. package/dist/apis/host.gtkx.js.map +1 -1
  12. package/dist/apis/host.js.map +1 -1
  13. package/dist/apis/i18n-manager.d.ts +14 -0
  14. package/dist/apis/i18n-manager.js +20 -0
  15. package/dist/apis/i18n-manager.js.map +1 -0
  16. package/dist/apis/index.d.ts +17 -0
  17. package/dist/apis/index.js +5 -0
  18. package/dist/apis/index.js.map +1 -1
  19. package/dist/apis/interaction-manager.d.ts +16 -0
  20. package/dist/apis/interaction-manager.js +96 -0
  21. package/dist/apis/interaction-manager.js.map +1 -0
  22. package/dist/apis/linking.d.ts +4 -0
  23. package/dist/apis/linking.js +9 -0
  24. package/dist/apis/linking.js.map +1 -1
  25. package/dist/components/app-registry.d.ts +2 -0
  26. package/dist/components/app-registry.js +19 -2
  27. package/dist/components/app-registry.js.map +1 -1
  28. package/dist/components/flat-list.d.ts +2 -0
  29. package/dist/components/flat-list.js.map +1 -1
  30. package/dist/components/index.d.ts +1 -1
  31. package/dist/components/index.js +1 -1
  32. package/dist/components/index.js.map +1 -1
  33. package/dist/components/modal.d.ts +1 -1
  34. package/dist/components/pressable.js +4 -4
  35. package/dist/components/pressable.js.map +1 -1
  36. package/dist/components/root.d.ts +10 -1
  37. package/dist/components/root.js +39 -1
  38. package/dist/components/root.js.map +1 -1
  39. package/dist/components/scroll-view.js +58 -5
  40. package/dist/components/scroll-view.js.map +1 -1
  41. package/dist/components/text-input.d.ts +1 -0
  42. package/dist/components/text-input.js +34 -5
  43. package/dist/components/text-input.js.map +1 -1
  44. package/dist/components/use-layout-child.d.ts +1 -1
  45. package/dist/components/use-layout-child.js +22 -2
  46. package/dist/components/use-layout-child.js.map +1 -1
  47. package/dist/components/virtualized-list.d.ts +2 -0
  48. package/dist/components/virtualized-list.js +132 -10
  49. package/dist/components/virtualized-list.js.map +1 -1
  50. package/dist/contracts.js +2 -3
  51. package/dist/contracts.js.map +1 -1
  52. package/dist/gtkx/bridge/index.d.ts +4 -2
  53. package/dist/gtkx/bridge/index.js +7 -3
  54. package/dist/gtkx/bridge/index.js.map +1 -1
  55. package/dist/gtkx/bridge/measure.js +5 -0
  56. package/dist/gtkx/bridge/measure.js.map +1 -1
  57. package/dist/gtkx/bridge/theme.js +1 -1
  58. package/dist/gtkx/bridge/theme.js.map +1 -1
  59. package/dist/gtkx/bridge/use-signal.d.ts +2 -0
  60. package/dist/gtkx/bridge/use-signal.js +31 -0
  61. package/dist/gtkx/bridge/use-signal.js.map +1 -0
  62. package/dist/index.d.ts +2 -2
  63. package/dist/index.js +3 -3
  64. package/dist/index.js.map +1 -1
  65. package/dist/layout/engine.d.ts +4 -0
  66. package/dist/layout/engine.js +97 -5
  67. package/dist/layout/engine.js.map +1 -1
  68. package/dist/layout/node.d.ts +1 -1
  69. package/dist/layout/node.js +8 -5
  70. package/dist/layout/node.js.map +1 -1
  71. package/dist/metro/index.js +1 -0
  72. package/dist/metro/index.js.map +1 -1
  73. package/dist/navigation/index.d.ts +44 -0
  74. package/dist/navigation/index.js +216 -0
  75. package/dist/navigation/index.js.map +1 -0
  76. package/dist/navigation/option-warnings.d.ts +2 -0
  77. package/dist/navigation/option-warnings.js +61 -0
  78. package/dist/navigation/option-warnings.js.map +1 -0
  79. package/dist/navigation/sidebar.d.ts +37 -0
  80. package/dist/navigation/sidebar.js +71 -0
  81. package/dist/navigation/sidebar.js.map +1 -0
  82. package/dist/perf.d.ts +9 -0
  83. package/dist/perf.js +156 -0
  84. package/dist/perf.js.map +1 -0
  85. package/dist/runner/host-dev.js +15 -6
  86. package/dist/runner/host-dev.js.map +1 -1
  87. package/dist/runner/host.js +24 -9
  88. package/dist/runner/host.js.map +1 -1
  89. package/dist/runner/index.js +7 -3
  90. package/dist/runner/index.js.map +1 -1
  91. package/dist/style/colors.js +3 -1
  92. package/dist/style/colors.js.map +1 -1
  93. package/dist/style/index.js +2 -2
  94. package/dist/style/index.js.map +1 -1
  95. package/dist/style/registry.gtkx.js +1 -1
  96. package/dist/style/registry.gtkx.js.map +1 -1
  97. package/dist/style/split-style.js +1 -1
  98. package/dist/style/split-style.js.map +1 -1
  99. package/dist/style/text-align.js +1 -1
  100. package/dist/style/text-align.js.map +1 -1
  101. package/dist/vite/index.d.ts +5 -4
  102. package/dist/vite/index.js +42 -7
  103. package/dist/vite/index.js.map +1 -1
  104. package/package.json +18 -10
  105. package/types.d.ts +13 -0
package/dist/perf.js ADDED
@@ -0,0 +1,156 @@
1
+ // TEMPORARY perf instrumentation for the scroll-lag investigation
2
+ // (perf-scroll branch). Enabled only when GTKX_PERF=1 is set in the
3
+ // environment; otherwise every hook is a cheap boolean check. Counters are
4
+ // accumulated and dumped once per second as a single machine-parseable
5
+ // stdout line: `GTKX_PERF {json}`. Pure JS — no FFI — so it is safe to
6
+ // import from any module in the package.
7
+ export const perfEnabled = typeof process !== "undefined" && process.env.GTKX_PERF === "1";
8
+ const counters = new Map();
9
+ // Duration accumulators (ms) with call counts and max, keyed by name.
10
+ const timers = new Map();
11
+ // Per-frame burst accumulators: reset on every frame-clock tick, reported as
12
+ // the WORST single frame of the second. A stall is invisible in per-second
13
+ // sums (a 12-mount burst inside one frame and 12 mounts spread over a second
14
+ // sum identically) — the burst maxima are what a flick actually feels like.
15
+ const frameBurst = new Map();
16
+ const frameBurstMax = new Map();
17
+ // Frame-clock interval tracking: deltas between consecutive ticks.
18
+ let lastFrameAt = -1;
19
+ let frameCount = 0;
20
+ // A healthy 60Hz tick jitters 16.6-16.9ms, so 17ms would count noise:
21
+ // "late" = one visibly stretched frame (>20ms), "veryLate" = at least one
22
+ // whole frame dropped (>34ms).
23
+ let frameLate = 0; // interval > 20ms
24
+ let frameVeryLate = 0; // interval > 34ms
25
+ let frameMaxMs = 0;
26
+ let frameTotalMs = 0;
27
+ export const perfCount = (name, n = 1) => {
28
+ if (!perfEnabled) {
29
+ return;
30
+ }
31
+ counters.set(name, (counters.get(name) ?? 0) + n);
32
+ };
33
+ export const perfNow = () => performance.now();
34
+ export const perfAddTime = (name, ms) => {
35
+ if (!perfEnabled) {
36
+ return;
37
+ }
38
+ const entry = timers.get(name);
39
+ if (entry) {
40
+ entry.totalMs += ms;
41
+ entry.count += 1;
42
+ if (ms > entry.maxMs) {
43
+ entry.maxMs = ms;
44
+ }
45
+ }
46
+ else {
47
+ timers.set(name, { totalMs: ms, count: 1, maxMs: ms });
48
+ }
49
+ };
50
+ // Accumulates into the CURRENT frame's bucket (counts or ms); the reporter
51
+ // keeps only the worst frame of each second, under `<name>.max`.
52
+ export const perfBurst = (name, value = 1) => {
53
+ if (!perfEnabled) {
54
+ return;
55
+ }
56
+ frameBurst.set(name, (frameBurst.get(name) ?? 0) + value);
57
+ };
58
+ // A sampled level (not a rate): reported as the second's maximum, so keys
59
+ // like the live node count read as "how big did it get".
60
+ export const perfGauge = (name, value) => {
61
+ if (!perfEnabled) {
62
+ return;
63
+ }
64
+ if (value > (frameBurstMax.get(name) ?? 0)) {
65
+ frameBurstMax.set(name, value);
66
+ }
67
+ };
68
+ const rollFrameBurst = () => {
69
+ for (const [name, value] of frameBurst) {
70
+ if (value > (frameBurstMax.get(name) ?? 0)) {
71
+ frameBurstMax.set(name, value);
72
+ }
73
+ }
74
+ frameBurst.clear();
75
+ };
76
+ // Called from a GTK frame-clock tick callback; `now` in ms (performance.now).
77
+ export const perfFrameTick = (now) => {
78
+ if (!perfEnabled) {
79
+ return;
80
+ }
81
+ rollFrameBurst();
82
+ if (lastFrameAt >= 0) {
83
+ const delta = now - lastFrameAt;
84
+ // A gap over 250ms means the frame clock paused (idle) — not a late
85
+ // frame; restart the interval chain instead of recording it.
86
+ if (delta < 250) {
87
+ frameCount += 1;
88
+ frameTotalMs += delta;
89
+ if (delta > 20) {
90
+ frameLate += 1;
91
+ }
92
+ if (delta > 34) {
93
+ frameVeryLate += 1;
94
+ }
95
+ if (delta > frameMaxMs) {
96
+ frameMaxMs = delta;
97
+ }
98
+ }
99
+ }
100
+ lastFrameAt = now;
101
+ };
102
+ // Marks phases (driven by the probe app) so the log parser can attribute
103
+ // per-second stats to scroll phases.
104
+ export const perfMark = (label) => {
105
+ if (!perfEnabled) {
106
+ return;
107
+ }
108
+ // eslint-disable-next-line no-console -- deliberate script-facing output
109
+ console.log(`GTKX_PERF_MARK ${label} ${performance.now().toFixed(1)}`);
110
+ };
111
+ let reporterStarted = false;
112
+ const dump = () => {
113
+ const out = {};
114
+ for (const [name, value] of counters) {
115
+ out[name] = value;
116
+ }
117
+ counters.clear();
118
+ for (const [name, entry] of timers) {
119
+ out[`${name}.ms`] = Math.round(entry.totalMs * 100) / 100;
120
+ out[`${name}.n`] = entry.count;
121
+ out[`${name}.max`] = Math.round(entry.maxMs * 100) / 100;
122
+ }
123
+ timers.clear();
124
+ // The tail of the second has not been rolled by a tick yet.
125
+ rollFrameBurst();
126
+ for (const [name, value] of frameBurstMax) {
127
+ out[`${name}.max`] = Math.round(value * 100) / 100;
128
+ }
129
+ frameBurstMax.clear();
130
+ if (frameCount > 0) {
131
+ out["frame.count"] = frameCount;
132
+ out["frame.late"] = frameLate;
133
+ out["frame.veryLate"] = frameVeryLate;
134
+ out["frame.max"] = Math.round(frameMaxMs * 100) / 100;
135
+ out["frame.avg"] = Math.round((frameTotalMs / frameCount) * 100) / 100;
136
+ }
137
+ frameCount = 0;
138
+ frameLate = 0;
139
+ frameVeryLate = 0;
140
+ frameMaxMs = 0;
141
+ frameTotalMs = 0;
142
+ if (Object.keys(out).length === 0) {
143
+ return;
144
+ }
145
+ out.t = Math.round(performance.now());
146
+ // eslint-disable-next-line no-console -- deliberate script-facing output
147
+ console.log(`GTKX_PERF ${JSON.stringify(out)}`);
148
+ };
149
+ export const ensurePerfReporter = () => {
150
+ if (!perfEnabled || reporterStarted) {
151
+ return;
152
+ }
153
+ reporterStarted = true;
154
+ setInterval(dump, 1000);
155
+ };
156
+ //# sourceMappingURL=perf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perf.js","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"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","sourcesContent":["// TEMPORARY perf instrumentation for the scroll-lag investigation\n// (perf-scroll branch). Enabled only when GTKX_PERF=1 is set in the\n// environment; otherwise every hook is a cheap boolean check. Counters are\n// accumulated and dumped once per second as a single machine-parseable\n// stdout line: `GTKX_PERF {json}`. Pure JS — no FFI — so it is safe to\n// import from any module in the package.\n\nexport const perfEnabled =\n typeof process !== \"undefined\" && process.env.GTKX_PERF === \"1\"\n\nconst counters = new Map<string, number>()\n// Duration accumulators (ms) with call counts and max, keyed by name.\nconst timers = new Map<\n string,\n { totalMs: number; count: number; maxMs: number }\n>()\n// Per-frame burst accumulators: reset on every frame-clock tick, reported as\n// the WORST single frame of the second. A stall is invisible in per-second\n// sums (a 12-mount burst inside one frame and 12 mounts spread over a second\n// sum identically) — the burst maxima are what a flick actually feels like.\nconst frameBurst = new Map<string, number>()\nconst frameBurstMax = new Map<string, number>()\n\n// Frame-clock interval tracking: deltas between consecutive ticks.\nlet lastFrameAt = -1\nlet frameCount = 0\n// A healthy 60Hz tick jitters 16.6-16.9ms, so 17ms would count noise:\n// \"late\" = one visibly stretched frame (>20ms), \"veryLate\" = at least one\n// whole frame dropped (>34ms).\nlet frameLate = 0 // interval > 20ms\nlet frameVeryLate = 0 // interval > 34ms\nlet frameMaxMs = 0\nlet frameTotalMs = 0\n\nexport const perfCount = (name: string, n = 1): void => {\n if (!perfEnabled) {\n return\n }\n counters.set(name, (counters.get(name) ?? 0) + n)\n}\n\nexport const perfNow = (): number => performance.now()\n\nexport const perfAddTime = (name: string, ms: number): void => {\n if (!perfEnabled) {\n return\n }\n const entry = timers.get(name)\n if (entry) {\n entry.totalMs += ms\n entry.count += 1\n if (ms > entry.maxMs) {\n entry.maxMs = ms\n }\n } else {\n timers.set(name, { totalMs: ms, count: 1, maxMs: ms })\n }\n}\n\n// Accumulates into the CURRENT frame's bucket (counts or ms); the reporter\n// keeps only the worst frame of each second, under `<name>.max`.\nexport const perfBurst = (name: string, value = 1): void => {\n if (!perfEnabled) {\n return\n }\n frameBurst.set(name, (frameBurst.get(name) ?? 0) + value)\n}\n\n// A sampled level (not a rate): reported as the second's maximum, so keys\n// like the live node count read as \"how big did it get\".\nexport const perfGauge = (name: string, value: number): void => {\n if (!perfEnabled) {\n return\n }\n if (value > (frameBurstMax.get(name) ?? 0)) {\n frameBurstMax.set(name, value)\n }\n}\n\nconst rollFrameBurst = (): void => {\n for (const [name, value] of frameBurst) {\n if (value > (frameBurstMax.get(name) ?? 0)) {\n frameBurstMax.set(name, value)\n }\n }\n frameBurst.clear()\n}\n\n// Called from a GTK frame-clock tick callback; `now` in ms (performance.now).\nexport const perfFrameTick = (now: number): void => {\n if (!perfEnabled) {\n return\n }\n rollFrameBurst()\n if (lastFrameAt >= 0) {\n const delta = now - lastFrameAt\n // A gap over 250ms means the frame clock paused (idle) — not a late\n // frame; restart the interval chain instead of recording it.\n if (delta < 250) {\n frameCount += 1\n frameTotalMs += delta\n if (delta > 20) {\n frameLate += 1\n }\n if (delta > 34) {\n frameVeryLate += 1\n }\n if (delta > frameMaxMs) {\n frameMaxMs = delta\n }\n }\n }\n lastFrameAt = now\n}\n\n// Marks phases (driven by the probe app) so the log parser can attribute\n// per-second stats to scroll phases.\nexport const perfMark = (label: string): void => {\n if (!perfEnabled) {\n return\n }\n // eslint-disable-next-line no-console -- deliberate script-facing output\n console.log(`GTKX_PERF_MARK ${label} ${performance.now().toFixed(1)}`)\n}\n\nlet reporterStarted = false\n\nconst dump = (): void => {\n const out: Record<string, number> = {}\n for (const [name, value] of counters) {\n out[name] = value\n }\n counters.clear()\n for (const [name, entry] of timers) {\n out[`${name}.ms`] = Math.round(entry.totalMs * 100) / 100\n out[`${name}.n`] = entry.count\n out[`${name}.max`] = Math.round(entry.maxMs * 100) / 100\n }\n timers.clear()\n // The tail of the second has not been rolled by a tick yet.\n rollFrameBurst()\n for (const [name, value] of frameBurstMax) {\n out[`${name}.max`] = Math.round(value * 100) / 100\n }\n frameBurstMax.clear()\n if (frameCount > 0) {\n out[\"frame.count\"] = frameCount\n out[\"frame.late\"] = frameLate\n out[\"frame.veryLate\"] = frameVeryLate\n out[\"frame.max\"] = Math.round(frameMaxMs * 100) / 100\n out[\"frame.avg\"] = Math.round((frameTotalMs / frameCount) * 100) / 100\n }\n frameCount = 0\n frameLate = 0\n frameVeryLate = 0\n frameMaxMs = 0\n frameTotalMs = 0\n if (Object.keys(out).length === 0) {\n return\n }\n out.t = Math.round(performance.now())\n // eslint-disable-next-line no-console -- deliberate script-facing output\n console.log(`GTKX_PERF ${JSON.stringify(out)}`)\n}\n\nexport const ensurePerfReporter = (): void => {\n if (!perfEnabled || reporterStarted) {\n return\n }\n reporterStarted = true\n setInterval(dump, 1000)\n}\n"]}
@@ -22,7 +22,7 @@ const fail = (message) => {
22
22
  process.exit(1);
23
23
  };
24
24
  if (typeof registerHooks !== "function") {
25
- fail(`Node ${process.version} lacks module.registerHooks — the linux host needs Node >= 22.15.`);
25
+ fail(`Node ${process.version} lacks module.registerHooks — the linux host needs Node >= 24.`);
26
26
  }
27
27
  // react and the reconciler must run their DEV builds for react-refresh.
28
28
  process.env.NODE_ENV = process.env.NODE_ENV ?? "development";
@@ -49,18 +49,27 @@ globalThis.__ReactRefresh = {
49
49
  process.exit(65);
50
50
  },
51
51
  };
52
- // --- virtual:gtkx-config (same mechanism as the release host).
53
- const { loadConfig } = await import(pathToFileURL(fromPackage.resolve("@gtkx/config")).href);
54
- const { config: gtkxConfig } = await loadConfig(process.cwd());
52
+ // --- virtual:gtkx-config (same mechanism and same module shape as the
53
+ // release host see host.ts for why each export is needed).
54
+ const CONFIG_REQUIRED = "gtkx.config.ts with an applicationId is required in the app root " +
55
+ '(export default defineConfig({ applicationId: "...", libraries: [...] })).';
56
+ const { createConfigLoader } = await import(pathToFileURL(fromPackage.resolve("@gtkx/config/internal")).href);
57
+ const gtkxConfig = await createConfigLoader()(process.cwd()).catch((error) => fail(`${CONFIG_REQUIRED}\n${String(error)}`));
55
58
  if (!gtkxConfig.applicationId) {
56
- fail("gtkx.config.ts with an applicationId is required in the app root " +
57
- '(export default defineConfig({ applicationId: "...", libraries: [...] })).');
59
+ fail(CONFIG_REQUIRED);
60
+ }
61
+ if (gtkxConfig.elements !== null) {
62
+ fail("gtkx.config.ts `elements.behaviors` is not supported on the linux " +
63
+ "platform — react-native-gtkx owns element behaviors.");
58
64
  }
59
65
  const configModuleUrl = new URL("./__virtual-gtkx-config.mjs", import.meta.url)
60
66
  .href;
67
+ const lazyElements = Object.fromEntries(gtkxConfig.lazyElements.map((type) => [type, { lazy: true }]));
61
68
  const configModuleSource = [
62
69
  `export * from "@gtkx/jsx/metadata";`,
63
70
  `export const applicationId = ${JSON.stringify(gtkxConfig.applicationId)};`,
71
+ `export const userEventSignals = ${JSON.stringify(gtkxConfig.userEventSignals)};`,
72
+ `export const elements = ${JSON.stringify(lazyElements)};`,
64
73
  ].join("\n");
65
74
  registerHooks({
66
75
  resolve(specifier, context, nextResolve) {
@@ -1 +1 @@
1
- {"version":3,"file":"host-dev.js","sourceRoot":"","sources":["../../src/runner/host-dev.ts"],"names":[],"mappings":"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","sourcesContent":["// The DEV host: fetch the dev bundle from a Metro dev server, execute it,\n// subscribe to HMR updates and let react-refresh re-render through the\n// @gtkx/react reconciler with component state preserved. Spawned by\n// `run-linux --dev` as `node dist/runner/host-dev.js <bundle-url>`; exits\n// with code 65 when a full refresh is required — the supervisor restarts.\n//\n// Division of labor (validated by spike/rn-platform, FINDINGS-dev.md):\n// metro-runtime's dev require scopes the react-refresh registration per\n// module and applies hot updates once global.__ReactRefresh exists; its\n// HMRClient speaks the /hot websocket protocol verbatim over Node's\n// global WebSocket. This file only adds the dev pieces on top of the\n// release host (./host.ts — deliberately self-contained twins: both must\n// stay runnable under bare Node, so they cannot share a relative\n// extensionless import).\nimport { createRequire, registerHooks } from \"node:module\"\nimport { join } from \"node:path\"\nimport { pathToFileURL } from \"node:url\"\nimport vm from \"node:vm\"\nimport { HOST_MODULE_EXTERNALS } from \"react-native-gtkx/metro\"\n\ntype HostModule = Record<string, unknown>\n\nconst fail = (message: string): never => {\n console.error(`[react-native-gtkx] ${message}`)\n process.exit(1)\n}\n\nif (typeof registerHooks !== \"function\") {\n fail(\n `Node ${process.version} lacks module.registerHooks — the linux host needs Node >= 22.15.`,\n )\n}\n\n// react and the reconciler must run their DEV builds for react-refresh.\nprocess.env.NODE_ENV = process.env.NODE_ENV ?? \"development\"\n\nconst bundleUrl = process.argv[2]\nif (!bundleUrl) {\n fail(\"usage: node host-dev.js <metro-dev-bundle-url>\")\n}\n\n// Resolution anchors: react-refresh and metro-runtime ship with the APP's\n// react-native; @gtkx/* resolve as this package's dependencies; react must\n// be the exact instance the reconciler sees (see host.ts).\nconst fromApp = createRequire(join(process.cwd(), \"package.json\"))\nconst fromPackage = createRequire(import.meta.url)\nconst fromGtkxReact = createRequire(fromPackage.resolve(\"@gtkx/react\"))\n\n// --- react-refresh: inject BEFORE @gtkx/react loads (the reconciler\n// registers into the patched devtools hook).\nconst RefreshRuntime = fromApp(\"react-refresh/runtime\") as Record<\n string,\n unknown\n> & { injectIntoGlobalHook(target: unknown): void }\nRefreshRuntime.injectIntoGlobalHook(globalThis)\nglobalThis.$RefreshReg$ = () => {}\nglobalThis.$RefreshSig$ = () => (type: unknown) => type\nglobalThis.__ReactRefresh = {\n ...RefreshRuntime,\n performFullRefresh(reason: string) {\n console.warn(\n `[react-native-gtkx] full refresh required (${reason}) — restarting`,\n )\n process.exit(65)\n },\n}\n\n// --- virtual:gtkx-config (same mechanism as the release host).\nconst { loadConfig } = await import(\n pathToFileURL(fromPackage.resolve(\"@gtkx/config\")).href\n)\nconst { config: gtkxConfig } = await loadConfig(process.cwd())\nif (!gtkxConfig.applicationId) {\n fail(\n \"gtkx.config.ts with an applicationId is required in the app root \" +\n '(export default defineConfig({ applicationId: \"...\", libraries: [...] })).',\n )\n}\nconst configModuleUrl = new URL(\"./__virtual-gtkx-config.mjs\", import.meta.url)\n .href\nconst configModuleSource = [\n `export * from \"@gtkx/jsx/metadata\";`,\n `export const applicationId = ${JSON.stringify(gtkxConfig.applicationId)};`,\n].join(\"\\n\")\nregisterHooks({\n resolve(specifier, context, nextResolve) {\n if (specifier === \"virtual:gtkx-config\") {\n return { url: configModuleUrl, shortCircuit: true }\n }\n return nextResolve(specifier, context)\n },\n load(url, context, nextLoad) {\n if (url === configModuleUrl) {\n return {\n format: \"module\",\n source: configModuleSource,\n shortCircuit: true,\n }\n }\n return nextLoad(url, context)\n },\n})\n\n// --- host modules (same interop merging as the release host).\nconst resolveExternal = (name: string): string =>\n name === \"react\" || name.startsWith(\"react/\")\n ? fromGtkxReact.resolve(name)\n : fromPackage.resolve(name)\n\nconst load = async (name: string): Promise<HostModule> => {\n const namespace: HostModule = await import(\n pathToFileURL(resolveExternal(name)).href\n )\n const merged: HostModule = { __esModule: true, ...namespace }\n if (!(\"default\" in namespace)) {\n merged.default = namespace\n }\n return merged\n}\n\nglobalThis.__hostModules = {}\nfor (const name of HOST_MODULE_EXTERNALS) {\n try {\n globalThis.__hostModules[name] = await load(name)\n } catch (error) {\n fail(\n `failed to load host module \"${name}\" — is the codegen store in ` +\n `place (npx gtkx codegen) and GTK4/libadwaita installed?\\n${String(error)}`,\n )\n }\n}\nglobalThis.__hostRequire = createRequire(import.meta.url)\n\n// --- Dev Menu (Ctrl+Shift+D, the react-native-windows precedent).\n// Installed before the bundle runs so DevSettings.reload works from app\n// code; the key controller attaches once the app window exists.\nconst requestReload = (reason?: string): never => {\n console.warn(\n `[react-native-gtkx] reload requested${reason ? ` (${reason})` : \"\"} — restarting`,\n )\n return process.exit(65)\n}\nglobalThis.__rnGtkxDevHost = { reload: requestReload }\n\n// Structural slices of the GTK wrappers the menu touches — the host talks\n// to codegen namespaces through __hostModules, untyped by design.\ntype DevMenuWindow = { addController(controller: unknown): void }\ntype DevMenuDialog = {\n setHeading(heading: string): void\n setBody(body: string): void\n addResponse(id: string, label: string): void\n setResponseAppearance(id: string, appearance: unknown): void\n setDefaultResponse(id: string): void\n setCloseResponse(id: string): void\n choose(parent: DevMenuWindow): Promise<string>\n}\n\nconst installDevMenu = (): void => {\n const gtk = globalThis.__hostModules[\"@gtkx/gi/gtk\"] as {\n EventControllerKey: new () => {\n on(signal: string, handler: (...args: unknown[]) => unknown): void\n }\n }\n const gdk = globalThis.__hostModules[\"@gtkx/gi/gdk\"] as {\n ModifierType: { CONTROL_MASK: number; SHIFT_MASK: number }\n }\n const adw = globalThis.__hostModules[\"@gtkx/gi/adw\"] as {\n AlertDialog: new () => DevMenuDialog\n ResponseAppearance: { SUGGESTED: unknown }\n }\n const gio = globalThis.__hostModules[\"@gtkx/gi/gio\"] as {\n Application: {\n getDefault():\n { getActiveWindow?: () => DevMenuWindow | null } | null | undefined\n }\n }\n // GDK keysyms for latin letters equal their ASCII codes.\n const KEY_UPPER_D = 0x44\n const KEY_LOWER_D = 0x64\n\n let menuOpen = false\n const openDevMenu = async (window: DevMenuWindow): Promise<void> => {\n if (menuOpen) {\n return\n }\n menuOpen = true\n try {\n const items = globalThis.__rnGtkxDevMenuItems ?? []\n const dialog = new adw.AlertDialog()\n dialog.setHeading(\"React Native Dev Menu\")\n dialog.setBody(bundleUrl!)\n dialog.addResponse(\"cancel\", \"Cancel\")\n items.forEach((item, index) => {\n dialog.addResponse(`custom-${index}`, item.title)\n })\n dialog.addResponse(\"reload\", \"Reload\")\n dialog.setResponseAppearance(\"reload\", adw.ResponseAppearance.SUGGESTED)\n dialog.setDefaultResponse(\"reload\")\n dialog.setCloseResponse(\"cancel\")\n const response = await dialog.choose(window)\n if (response === \"reload\") {\n requestReload()\n }\n const custom = /^custom-(\\d+)$/.exec(response)\n if (custom) {\n items[Number(custom[1])]?.handler()\n }\n } catch (error) {\n console.error(`[react-native-gtkx] dev menu failed: ${String(error)}`)\n } finally {\n menuOpen = false\n }\n }\n\n const attach = (): void => {\n const window = gio.Application.getDefault()?.getActiveWindow?.()\n if (!window) {\n // The bundle opens the window asynchronously (application activate).\n setTimeout(attach, 200)\n return\n }\n const controller = new gtk.EventControllerKey()\n controller.on(\"key-pressed\", (keyval, _keycode, state) => {\n const modifiers = state as number\n const wanted =\n (modifiers & gdk.ModifierType.CONTROL_MASK) !== 0 &&\n (modifiers & gdk.ModifierType.SHIFT_MASK) !== 0 &&\n (keyval === KEY_UPPER_D || keyval === KEY_LOWER_D)\n if (wanted) {\n void openDevMenu(window)\n return true\n }\n return false\n })\n window.addController(controller)\n console.warn(\"[react-native-gtkx] dev menu ready (Ctrl+Shift+D)\")\n }\n attach()\n}\n\n// --- fetch and run the dev bundle.\nlet response: Response\ntry {\n response = await fetch(bundleUrl!)\n} catch {\n fail(`Metro dev server is not reachable (${bundleUrl}).`)\n throw new Error(\"unreachable\")\n}\nif (!response.ok) {\n fail(\n `Metro returned ${response.status} for the dev bundle:\\n${await response.text()}`,\n )\n}\nvm.runInThisContext(await response.text(), { filename: bundleUrl })\ninstallDevMenu()\n\n// --- HMR: metro-runtime's own client (ships with react-native).\ntype HmrErrorBody = { type?: string; message?: string }\ntype HmrClient = {\n send(message: string): void\n enable(): void\n on(event: string, listener: (body?: HmrErrorBody) => void): void\n}\nconst HMRClient = fromApp(\"metro-runtime/src/modules/HMRClient\") as new (\n url: string,\n) => HmrClient\nconst client = new HMRClient(\n bundleUrl!.replace(/^http/, \"ws\").replace(/\\/[^/]*$/, \"/hot\"),\n)\nclient.send(\n JSON.stringify({ type: \"register-entrypoints\", entryPoints: [bundleUrl] }),\n)\nclient.enable()\nclient.on(\"update-done\", () => {\n console.warn(\"[react-native-gtkx] hot update applied\")\n})\nclient.on(\"error\", (body) => {\n console.error(\n `[react-native-gtkx] Metro error (${body?.type ?? \"unknown\"}):\\n${body?.message ?? \"\"}`,\n )\n})\nclient.on(\"close\", () => {\n console.warn(\n \"[react-native-gtkx] HMR connection closed (the window keeps running without hot updates)\",\n )\n})\n"]}
1
+ {"version":3,"file":"host-dev.js","sourceRoot":"","sources":["../../src/runner/host-dev.ts"],"names":[],"mappings":"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","sourcesContent":["// The DEV host: fetch the dev bundle from a Metro dev server, execute it,\n// subscribe to HMR updates and let react-refresh re-render through the\n// @gtkx/react reconciler with component state preserved. Spawned by\n// `run-linux --dev` as `node dist/runner/host-dev.js <bundle-url>`; exits\n// with code 65 when a full refresh is required — the supervisor restarts.\n//\n// Division of labor (validated by spike/rn-platform, FINDINGS-dev.md):\n// metro-runtime's dev require scopes the react-refresh registration per\n// module and applies hot updates once global.__ReactRefresh exists; its\n// HMRClient speaks the /hot websocket protocol verbatim over Node's\n// global WebSocket. This file only adds the dev pieces on top of the\n// release host (./host.ts — deliberately self-contained twins: both must\n// stay runnable under bare Node, so they cannot share a relative\n// extensionless import).\nimport { createRequire, registerHooks } from \"node:module\"\nimport { join } from \"node:path\"\nimport { pathToFileURL } from \"node:url\"\nimport vm from \"node:vm\"\nimport { HOST_MODULE_EXTERNALS } from \"react-native-gtkx/metro\"\n\ntype HostModule = Record<string, unknown>\n\nconst fail = (message: string): never => {\n console.error(`[react-native-gtkx] ${message}`)\n process.exit(1)\n}\n\nif (typeof registerHooks !== \"function\") {\n fail(\n `Node ${process.version} lacks module.registerHooks — the linux host needs Node >= 24.`,\n )\n}\n\n// react and the reconciler must run their DEV builds for react-refresh.\nprocess.env.NODE_ENV = process.env.NODE_ENV ?? \"development\"\n\nconst bundleUrl = process.argv[2]\nif (!bundleUrl) {\n fail(\"usage: node host-dev.js <metro-dev-bundle-url>\")\n}\n\n// Resolution anchors: react-refresh and metro-runtime ship with the APP's\n// react-native; @gtkx/* resolve as this package's dependencies; react must\n// be the exact instance the reconciler sees (see host.ts).\nconst fromApp = createRequire(join(process.cwd(), \"package.json\"))\nconst fromPackage = createRequire(import.meta.url)\nconst fromGtkxReact = createRequire(fromPackage.resolve(\"@gtkx/react\"))\n\n// --- react-refresh: inject BEFORE @gtkx/react loads (the reconciler\n// registers into the patched devtools hook).\nconst RefreshRuntime = fromApp(\"react-refresh/runtime\") as Record<\n string,\n unknown\n> & { injectIntoGlobalHook(target: unknown): void }\nRefreshRuntime.injectIntoGlobalHook(globalThis)\nglobalThis.$RefreshReg$ = () => {}\nglobalThis.$RefreshSig$ = () => (type: unknown) => type\nglobalThis.__ReactRefresh = {\n ...RefreshRuntime,\n performFullRefresh(reason: string) {\n console.warn(\n `[react-native-gtkx] full refresh required (${reason}) — restarting`,\n )\n process.exit(65)\n },\n}\n\n// --- virtual:gtkx-config (same mechanism and same module shape as the\n// release host — see host.ts for why each export is needed).\nconst CONFIG_REQUIRED =\n \"gtkx.config.ts with an applicationId is required in the app root \" +\n '(export default defineConfig({ applicationId: \"...\", libraries: [...] })).'\nconst { createConfigLoader } = await import(\n pathToFileURL(fromPackage.resolve(\"@gtkx/config/internal\")).href\n)\nconst gtkxConfig = await createConfigLoader()(process.cwd()).catch(\n (error: unknown) => fail(`${CONFIG_REQUIRED}\\n${String(error)}`),\n)\nif (!gtkxConfig.applicationId) {\n fail(CONFIG_REQUIRED)\n}\nif (gtkxConfig.elements !== null) {\n fail(\n \"gtkx.config.ts `elements.behaviors` is not supported on the linux \" +\n \"platform — react-native-gtkx owns element behaviors.\",\n )\n}\nconst configModuleUrl = new URL(\"./__virtual-gtkx-config.mjs\", import.meta.url)\n .href\nconst lazyElements = Object.fromEntries(\n gtkxConfig.lazyElements.map((type: string) => [type, { lazy: true }]),\n)\nconst configModuleSource = [\n `export * from \"@gtkx/jsx/metadata\";`,\n `export const applicationId = ${JSON.stringify(gtkxConfig.applicationId)};`,\n `export const userEventSignals = ${JSON.stringify(gtkxConfig.userEventSignals)};`,\n `export const elements = ${JSON.stringify(lazyElements)};`,\n].join(\"\\n\")\nregisterHooks({\n resolve(specifier, context, nextResolve) {\n if (specifier === \"virtual:gtkx-config\") {\n return { url: configModuleUrl, shortCircuit: true }\n }\n return nextResolve(specifier, context)\n },\n load(url, context, nextLoad) {\n if (url === configModuleUrl) {\n return {\n format: \"module\",\n source: configModuleSource,\n shortCircuit: true,\n }\n }\n return nextLoad(url, context)\n },\n})\n\n// --- host modules (same interop merging as the release host).\nconst resolveExternal = (name: string): string =>\n name === \"react\" || name.startsWith(\"react/\")\n ? fromGtkxReact.resolve(name)\n : fromPackage.resolve(name)\n\nconst load = async (name: string): Promise<HostModule> => {\n const namespace: HostModule = await import(\n pathToFileURL(resolveExternal(name)).href\n )\n const merged: HostModule = { __esModule: true, ...namespace }\n if (!(\"default\" in namespace)) {\n merged.default = namespace\n }\n return merged\n}\n\nglobalThis.__hostModules = {}\nfor (const name of HOST_MODULE_EXTERNALS) {\n try {\n globalThis.__hostModules[name] = await load(name)\n } catch (error) {\n fail(\n `failed to load host module \"${name}\" — is the codegen store in ` +\n `place (npx gtkx codegen) and GTK4/libadwaita installed?\\n${String(error)}`,\n )\n }\n}\nglobalThis.__hostRequire = createRequire(import.meta.url)\n\n// --- Dev Menu (Ctrl+Shift+D, the react-native-windows precedent).\n// Installed before the bundle runs so DevSettings.reload works from app\n// code; the key controller attaches once the app window exists.\nconst requestReload = (reason?: string): never => {\n console.warn(\n `[react-native-gtkx] reload requested${reason ? ` (${reason})` : \"\"} — restarting`,\n )\n return process.exit(65)\n}\nglobalThis.__rnGtkxDevHost = { reload: requestReload }\n\n// Structural slices of the GTK wrappers the menu touches — the host talks\n// to codegen namespaces through __hostModules, untyped by design.\ntype DevMenuWindow = { addController(controller: unknown): void }\ntype DevMenuDialog = {\n setHeading(heading: string): void\n setBody(body: string): void\n addResponse(id: string, label: string): void\n setResponseAppearance(id: string, appearance: unknown): void\n setDefaultResponse(id: string): void\n setCloseResponse(id: string): void\n choose(parent: DevMenuWindow): Promise<string>\n}\n\nconst installDevMenu = (): void => {\n const gtk = globalThis.__hostModules[\"@gtkx/gi/gtk\"] as {\n EventControllerKey: new () => {\n on(signal: string, handler: (...args: unknown[]) => unknown): void\n }\n }\n const gdk = globalThis.__hostModules[\"@gtkx/gi/gdk\"] as {\n ModifierType: { CONTROL_MASK: number; SHIFT_MASK: number }\n }\n const adw = globalThis.__hostModules[\"@gtkx/gi/adw\"] as {\n AlertDialog: new () => DevMenuDialog\n ResponseAppearance: { SUGGESTED: unknown }\n }\n const gio = globalThis.__hostModules[\"@gtkx/gi/gio\"] as {\n Application: {\n getDefault():\n { getActiveWindow?: () => DevMenuWindow | null } | null | undefined\n }\n }\n // GDK keysyms for latin letters equal their ASCII codes.\n const KEY_UPPER_D = 0x44\n const KEY_LOWER_D = 0x64\n\n let menuOpen = false\n const openDevMenu = async (window: DevMenuWindow): Promise<void> => {\n if (menuOpen) {\n return\n }\n menuOpen = true\n try {\n const items = globalThis.__rnGtkxDevMenuItems ?? []\n const dialog = new adw.AlertDialog()\n dialog.setHeading(\"React Native Dev Menu\")\n dialog.setBody(bundleUrl!)\n dialog.addResponse(\"cancel\", \"Cancel\")\n items.forEach((item, index) => {\n dialog.addResponse(`custom-${index}`, item.title)\n })\n dialog.addResponse(\"reload\", \"Reload\")\n dialog.setResponseAppearance(\"reload\", adw.ResponseAppearance.SUGGESTED)\n dialog.setDefaultResponse(\"reload\")\n dialog.setCloseResponse(\"cancel\")\n const response = await dialog.choose(window)\n if (response === \"reload\") {\n requestReload()\n }\n const custom = /^custom-(\\d+)$/.exec(response)\n if (custom) {\n items[Number(custom[1])]?.handler()\n }\n } catch (error) {\n console.error(`[react-native-gtkx] dev menu failed: ${String(error)}`)\n } finally {\n menuOpen = false\n }\n }\n\n const attach = (): void => {\n const window = gio.Application.getDefault()?.getActiveWindow?.()\n if (!window) {\n // The bundle opens the window asynchronously (application activate).\n setTimeout(attach, 200)\n return\n }\n const controller = new gtk.EventControllerKey()\n controller.on(\"key-pressed\", (keyval, _keycode, state) => {\n const modifiers = state as number\n const wanted =\n (modifiers & gdk.ModifierType.CONTROL_MASK) !== 0 &&\n (modifiers & gdk.ModifierType.SHIFT_MASK) !== 0 &&\n (keyval === KEY_UPPER_D || keyval === KEY_LOWER_D)\n if (wanted) {\n void openDevMenu(window)\n return true\n }\n return false\n })\n window.addController(controller)\n console.warn(\"[react-native-gtkx] dev menu ready (Ctrl+Shift+D)\")\n }\n attach()\n}\n\n// --- fetch and run the dev bundle.\nlet response: Response\ntry {\n response = await fetch(bundleUrl!)\n} catch {\n fail(`Metro dev server is not reachable (${bundleUrl}).`)\n throw new Error(\"unreachable\")\n}\nif (!response.ok) {\n fail(\n `Metro returned ${response.status} for the dev bundle:\\n${await response.text()}`,\n )\n}\nvm.runInThisContext(await response.text(), { filename: bundleUrl })\ninstallDevMenu()\n\n// --- HMR: metro-runtime's own client (ships with react-native).\ntype HmrErrorBody = { type?: string; message?: string }\ntype HmrClient = {\n send(message: string): void\n enable(): void\n on(event: string, listener: (body?: HmrErrorBody) => void): void\n}\nconst HMRClient = fromApp(\"metro-runtime/src/modules/HMRClient\") as new (\n url: string,\n) => HmrClient\nconst client = new HMRClient(\n bundleUrl!.replace(/^http/, \"ws\").replace(/\\/[^/]*$/, \"/hot\"),\n)\nclient.send(\n JSON.stringify({ type: \"register-entrypoints\", entryPoints: [bundleUrl] }),\n)\nclient.enable()\nclient.on(\"update-done\", () => {\n console.warn(\"[react-native-gtkx] hot update applied\")\n})\nclient.on(\"error\", (body) => {\n console.error(\n `[react-native-gtkx] Metro error (${body?.type ?? \"unknown\"}):\\n${body?.message ?? \"\"}`,\n )\n})\nclient.on(\"close\", () => {\n console.warn(\n \"[react-native-gtkx] HMR connection closed (the window keeps running without hot updates)\",\n )\n})\n"]}
@@ -16,7 +16,7 @@ const fail = (message) => {
16
16
  process.exit(1);
17
17
  };
18
18
  if (typeof registerHooks !== "function") {
19
- fail(`Node ${process.version} lacks module.registerHooks — the linux host needs Node >= 22.15.`);
19
+ fail(`Node ${process.version} lacks module.registerHooks — the linux host needs Node >= 24.`);
20
20
  }
21
21
  // Resolution anchors. @gtkx/* and @gtkx/config resolve as THIS package's
22
22
  // dependencies; react resolves FROM @gtkx/react's real location — the
@@ -37,21 +37,36 @@ const load = async (name) => {
37
37
  }
38
38
  return merged;
39
39
  };
40
- // @gtkx/react imports `virtual:gtkx-config` (JSX metadata + the resolved
41
- // applicationId); in the vite path the gtkx CLI plugin serves it. Replicate
42
- // it with a loader hook. The fake module URL is anchored inside this
43
- // package so the re-exported bare specifier resolves through node_modules.
44
- const { loadConfig } = await import("@gtkx/config");
45
- const { config: gtkxConfig } = await loadConfig(process.cwd());
40
+ // @gtkx/react imports `virtual:gtkx-config` JSX metadata plus the values
41
+ // resolved from gtkx.config.ts (applicationId for the GApplication, the
42
+ // userEventSignals suppressed during commits and the elements config the
43
+ // reconciler registry is primed with). In the vite path the gtkx CLI plugin
44
+ // serves it; replicate it with a loader hook, mirroring @gtkx/config's own
45
+ // renderConfigModule. The fake module URL is anchored inside this package so
46
+ // the re-exported bare specifier resolves through node_modules.
47
+ const CONFIG_REQUIRED = "gtkx.config.ts with an applicationId is required in the app root " +
48
+ '(export default defineConfig({ applicationId: "...", libraries: [...] })).';
49
+ const { createConfigLoader } = await import("@gtkx/config/internal");
50
+ // The loader validates the config, so a missing or malformed one throws.
51
+ const gtkxConfig = await createConfigLoader()(process.cwd()).catch((error) => fail(`${CONFIG_REQUIRED}\n${String(error)}`));
46
52
  if (!gtkxConfig.applicationId) {
47
- fail("gtkx.config.ts with an applicationId is required in the app root " +
48
- '(export default defineConfig({ applicationId: "...", libraries: [...] })).');
53
+ fail(CONFIG_REQUIRED);
54
+ }
55
+ // A behaviors module would have to be bundled and merged through
56
+ // @gtkx/react/config; the react-native surface owns element behaviors, so no
57
+ // app declares one — refuse rather than silently drop it.
58
+ if (gtkxConfig.elements !== null) {
59
+ fail("gtkx.config.ts `elements.behaviors` is not supported on the linux " +
60
+ "platform — react-native-gtkx owns element behaviors.");
49
61
  }
50
62
  const configModuleUrl = new URL("./__virtual-gtkx-config.mjs", import.meta.url)
51
63
  .href;
64
+ const lazyElements = Object.fromEntries(gtkxConfig.lazyElements.map((type) => [type, { lazy: true }]));
52
65
  const configModuleSource = [
53
66
  `export * from "@gtkx/jsx/metadata";`,
54
67
  `export const applicationId = ${JSON.stringify(gtkxConfig.applicationId)};`,
68
+ `export const userEventSignals = ${JSON.stringify(gtkxConfig.userEventSignals)};`,
69
+ `export const elements = ${JSON.stringify(lazyElements)};`,
55
70
  ].join("\n");
56
71
  registerHooks({
57
72
  resolve(specifier, context, nextResolve) {
@@ -1 +1 @@
1
- {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/runner/host.ts"],"names":[],"mappings":"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","sourcesContent":["// The Node+GTK host: executes a Metro jsbundle built for the linux\n// platform. Spawned by the run-linux command as\n// `node dist/runner/host.js <bundle>`; the bundle's externalized proxies\n// (see ../metro) read the modules injected here.\n//\n// This file must stay runnable under BARE Node: no extensionless relative\n// imports — only builtins, bare dependency specifiers and the package\n// self-reference (resolved through the exports map).\nimport { readFileSync } from \"node:fs\"\nimport { createRequire, registerHooks } from \"node:module\"\nimport { pathToFileURL } from \"node:url\"\nimport vm from \"node:vm\"\nimport { HOST_MODULE_EXTERNALS } from \"react-native-gtkx/metro\"\n\ntype HostModule = Record<string, unknown>\n\nconst fail = (message: string): never => {\n console.error(`[react-native-gtkx] ${message}`)\n process.exit(1)\n}\n\nif (typeof registerHooks !== \"function\") {\n fail(\n `Node ${process.version} lacks module.registerHooks — the linux host needs Node >= 22.15.`,\n )\n}\n\n// Resolution anchors. @gtkx/* and @gtkx/config resolve as THIS package's\n// dependencies; react resolves FROM @gtkx/react's real location — the\n// reconciler and the app must share one React instance, and anchoring at\n// the app could pick up a second copy installed by npm peer auto-install.\nconst fromPackage = createRequire(import.meta.url)\nconst fromGtkxReact = createRequire(fromPackage.resolve(\"@gtkx/react\"))\n\nconst resolveExternal = (name: string): string =>\n name === \"react\" || name.startsWith(\"react/\")\n ? fromGtkxReact.resolve(name)\n : fromPackage.resolve(name)\n\n// import() handles both ESM and CJS; merge a `default` for Babel's\n// default-import interop when the module has none of its own.\nconst load = async (name: string): Promise<HostModule> => {\n const namespace: HostModule = await import(\n pathToFileURL(resolveExternal(name)).href\n )\n const merged: HostModule = { __esModule: true, ...namespace }\n if (!(\"default\" in namespace)) {\n merged.default = namespace\n }\n return merged\n}\n\n// @gtkx/react imports `virtual:gtkx-config` (JSX metadata + the resolved\n// applicationId); in the vite path the gtkx CLI plugin serves it. Replicate\n// it with a loader hook. The fake module URL is anchored inside this\n// package so the re-exported bare specifier resolves through node_modules.\nconst { loadConfig } = await import(\"@gtkx/config\")\nconst { config: gtkxConfig } = await loadConfig(process.cwd())\nif (!gtkxConfig.applicationId) {\n fail(\n \"gtkx.config.ts with an applicationId is required in the app root \" +\n '(export default defineConfig({ applicationId: \"...\", libraries: [...] })).',\n )\n}\nconst configModuleUrl = new URL(\"./__virtual-gtkx-config.mjs\", import.meta.url)\n .href\nconst configModuleSource = [\n `export * from \"@gtkx/jsx/metadata\";`,\n `export const applicationId = ${JSON.stringify(gtkxConfig.applicationId)};`,\n].join(\"\\n\")\nregisterHooks({\n resolve(specifier, context, nextResolve) {\n if (specifier === \"virtual:gtkx-config\") {\n return { url: configModuleUrl, shortCircuit: true }\n }\n return nextResolve(specifier, context)\n },\n load(url, context, nextLoad) {\n if (url === configModuleUrl) {\n return {\n format: \"module\",\n source: configModuleSource,\n shortCircuit: true,\n }\n }\n return nextLoad(url, context)\n },\n})\n\nglobalThis.__hostModules = {}\nfor (const name of HOST_MODULE_EXTERNALS) {\n try {\n globalThis.__hostModules[name] = await load(name)\n } catch (error) {\n fail(\n `failed to load host module \"${name}\" — is the codegen store in ` +\n `place (npx gtkx codegen) and GTK4/libadwaita installed?\\n${String(error)}`,\n )\n }\n}\n// Node builtin proxies resolve lazily through the host's own require.\nglobalThis.__hostRequire = createRequire(import.meta.url)\n\nconst bundlePath = process.argv[2]\nif (!bundlePath) {\n fail(\"usage: node host.js <path/to/main.jsbundle>\")\n}\nlet source: string\ntry {\n source = readFileSync(bundlePath!, \"utf8\")\n} catch {\n fail(`bundle not found at ${bundlePath} — run react-native run-linux.`)\n throw new Error(\"unreachable\")\n}\n// The entry calls AppRegistry.runApplication itself (the react-native-web\n// pattern); the GLib main loop keeps the process alive afterwards.\nvm.runInThisContext(source, { filename: bundlePath })\n"]}
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/runner/host.ts"],"names":[],"mappings":"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","sourcesContent":["// The Node+GTK host: executes a Metro jsbundle built for the linux\n// platform. Spawned by the run-linux command as\n// `node dist/runner/host.js <bundle>`; the bundle's externalized proxies\n// (see ../metro) read the modules injected here.\n//\n// This file must stay runnable under BARE Node: no extensionless relative\n// imports — only builtins, bare dependency specifiers and the package\n// self-reference (resolved through the exports map).\nimport { readFileSync } from \"node:fs\"\nimport { createRequire, registerHooks } from \"node:module\"\nimport { pathToFileURL } from \"node:url\"\nimport vm from \"node:vm\"\nimport { HOST_MODULE_EXTERNALS } from \"react-native-gtkx/metro\"\n\ntype HostModule = Record<string, unknown>\n\nconst fail = (message: string): never => {\n console.error(`[react-native-gtkx] ${message}`)\n process.exit(1)\n}\n\nif (typeof registerHooks !== \"function\") {\n fail(\n `Node ${process.version} lacks module.registerHooks — the linux host needs Node >= 24.`,\n )\n}\n\n// Resolution anchors. @gtkx/* and @gtkx/config resolve as THIS package's\n// dependencies; react resolves FROM @gtkx/react's real location — the\n// reconciler and the app must share one React instance, and anchoring at\n// the app could pick up a second copy installed by npm peer auto-install.\nconst fromPackage = createRequire(import.meta.url)\nconst fromGtkxReact = createRequire(fromPackage.resolve(\"@gtkx/react\"))\n\nconst resolveExternal = (name: string): string =>\n name === \"react\" || name.startsWith(\"react/\")\n ? fromGtkxReact.resolve(name)\n : fromPackage.resolve(name)\n\n// import() handles both ESM and CJS; merge a `default` for Babel's\n// default-import interop when the module has none of its own.\nconst load = async (name: string): Promise<HostModule> => {\n const namespace: HostModule = await import(\n pathToFileURL(resolveExternal(name)).href\n )\n const merged: HostModule = { __esModule: true, ...namespace }\n if (!(\"default\" in namespace)) {\n merged.default = namespace\n }\n return merged\n}\n\n// @gtkx/react imports `virtual:gtkx-config` JSX metadata plus the values\n// resolved from gtkx.config.ts (applicationId for the GApplication, the\n// userEventSignals suppressed during commits and the elements config the\n// reconciler registry is primed with). In the vite path the gtkx CLI plugin\n// serves it; replicate it with a loader hook, mirroring @gtkx/config's own\n// renderConfigModule. The fake module URL is anchored inside this package so\n// the re-exported bare specifier resolves through node_modules.\nconst CONFIG_REQUIRED =\n \"gtkx.config.ts with an applicationId is required in the app root \" +\n '(export default defineConfig({ applicationId: \"...\", libraries: [...] })).'\nconst { createConfigLoader } = await import(\"@gtkx/config/internal\")\n// The loader validates the config, so a missing or malformed one throws.\nconst gtkxConfig = await createConfigLoader()(process.cwd()).catch(\n (error: unknown) => fail(`${CONFIG_REQUIRED}\\n${String(error)}`),\n)\nif (!gtkxConfig.applicationId) {\n fail(CONFIG_REQUIRED)\n}\n// A behaviors module would have to be bundled and merged through\n// @gtkx/react/config; the react-native surface owns element behaviors, so no\n// app declares one — refuse rather than silently drop it.\nif (gtkxConfig.elements !== null) {\n fail(\n \"gtkx.config.ts `elements.behaviors` is not supported on the linux \" +\n \"platform react-native-gtkx owns element behaviors.\",\n )\n}\nconst configModuleUrl = new URL(\"./__virtual-gtkx-config.mjs\", import.meta.url)\n .href\nconst lazyElements = Object.fromEntries(\n gtkxConfig.lazyElements.map((type) => [type, { lazy: true }]),\n)\nconst configModuleSource = [\n `export * from \"@gtkx/jsx/metadata\";`,\n `export const applicationId = ${JSON.stringify(gtkxConfig.applicationId)};`,\n `export const userEventSignals = ${JSON.stringify(gtkxConfig.userEventSignals)};`,\n `export const elements = ${JSON.stringify(lazyElements)};`,\n].join(\"\\n\")\nregisterHooks({\n resolve(specifier, context, nextResolve) {\n if (specifier === \"virtual:gtkx-config\") {\n return { url: configModuleUrl, shortCircuit: true }\n }\n return nextResolve(specifier, context)\n },\n load(url, context, nextLoad) {\n if (url === configModuleUrl) {\n return {\n format: \"module\",\n source: configModuleSource,\n shortCircuit: true,\n }\n }\n return nextLoad(url, context)\n },\n})\n\nglobalThis.__hostModules = {}\nfor (const name of HOST_MODULE_EXTERNALS) {\n try {\n globalThis.__hostModules[name] = await load(name)\n } catch (error) {\n fail(\n `failed to load host module \"${name}\" — is the codegen store in ` +\n `place (npx gtkx codegen) and GTK4/libadwaita installed?\\n${String(error)}`,\n )\n }\n}\n// Node builtin proxies resolve lazily through the host's own require.\nglobalThis.__hostRequire = createRequire(import.meta.url)\n\nconst bundlePath = process.argv[2]\nif (!bundlePath) {\n fail(\"usage: node host.js <path/to/main.jsbundle>\")\n}\nlet source: string\ntry {\n source = readFileSync(bundlePath!, \"utf8\")\n} catch {\n fail(`bundle not found at ${bundlePath} — run react-native run-linux.`)\n throw new Error(\"unreachable\")\n}\n// The entry calls AppRegistry.runApplication itself (the react-native-web\n// pattern); the GLib main loop keeps the process alive afterwards.\nvm.runInThisContext(source, { filename: bundlePath })\n"]}
@@ -30,10 +30,11 @@ const binOf = (requireFrom, packageName, binName) => {
30
30
  }
31
31
  return join(dirname(packageJsonPath), bin);
32
32
  };
33
+ // RC2-WORKAROUND(codegen-cwd): see docs/gtkx-rc2-notes.md
33
34
  // The codegen store lives in the node_modules that hosts the @gtkx
34
35
  // packages — run the gtkx CLI from the project that OWNS that node_modules:
35
- // with cwd inside node_modules itself the CLI reports "up to date" without
36
- // ever creating the store.
36
+ // with cwd inside node_modules itself the CLI reports "bindings up to date"
37
+ // without ever creating the store.
37
38
  const ensureCodegenStore = () => {
38
39
  const hostingNodeModules = dirname(dirname(dirname(fromPackage.resolve("@gtkx/react/package.json"))));
39
40
  const gtkxRoot = dirname(hostingNodeModules);
@@ -84,7 +85,10 @@ const waitForMetro = async (server) => {
84
85
  };
85
86
  let activeHost = null;
86
87
  const spawnHost = (script, argument, cwd) => new Promise((resolve) => {
87
- const hostPath = fileURLToPath(new URL(script, import.meta.url));
88
+ // join over `new URL(script, import.meta.url)`: the global URL and the
89
+ // node:url URL come from different type copies when the dependency tree
90
+ // splits @types/node, and the two structurally diverge.
91
+ const hostPath = join(dirname(fileURLToPath(import.meta.url)), script);
88
92
  const child = spawn(process.execPath, [hostPath, argument], {
89
93
  cwd,
90
94
  stdio: "inherit",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runner/index.ts"],"names":[],"mappings":"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","sourcesContent":["// The `run-linux` CLI command (registered through the package's\n// react-native.config.js, the react-native-windows model): ensure the gtkx\n// codegen store, then either build a release jsbundle with Metro and run\n// it in the Node+GTK host (./host.ts), or — with --dev — start/reuse a\n// Metro dev server and supervise the DEV host (./host-dev.ts): Fast\n// Refresh applies edits to the live window, and a full-refresh request\n// (exit code 65) restarts the host process.\n//\n// Like the hosts, this module must stay runnable under bare Node:\n// builtins and bare specifiers only.\nimport { spawn, spawnSync, type ChildProcess } from \"node:child_process\"\nimport { mkdirSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\nimport { basename, dirname, extname, join } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\nconst fromPackage = createRequire(import.meta.url)\n\ntype CliConfig = { root: string }\ntype RunLinuxArgs = {\n entryFile: string\n bundleOutput?: string\n skipBundling?: boolean\n dev?: boolean\n port?: string\n}\n\n/** Exit code host-dev.ts uses to request a supervisor restart. */\nconst FULL_REFRESH_EXIT_CODE = 65\n\nconst run = (command: string, args: string[], cwd: string): number => {\n const result = spawnSync(command, args, { cwd, stdio: \"inherit\" })\n return result.status ?? 1\n}\n\n/** Resolve an executable script shipped by a dependency's bin field. */\nconst binOf = (\n requireFrom: NodeJS.Require,\n packageName: string,\n binName: string,\n): string => {\n const packageJsonPath = requireFrom.resolve(`${packageName}/package.json`)\n const manifest = requireFrom(`${packageName}/package.json`) as {\n bin?: string | Record<string, string>\n }\n const bin =\n typeof manifest.bin === \"string\" ? manifest.bin : manifest.bin?.[binName]\n if (!bin) {\n throw new Error(`${packageName} does not expose a \"${binName}\" binary`)\n }\n return join(dirname(packageJsonPath), bin)\n}\n\n// The codegen store lives in the node_modules that hosts the @gtkx\n// packages — run the gtkx CLI from the project that OWNS that node_modules:\n// with cwd inside node_modules itself the CLI reports \"up to date\" without\n// ever creating the store.\nconst ensureCodegenStore = (): void => {\n const hostingNodeModules = dirname(\n dirname(dirname(fromPackage.resolve(\"@gtkx/react/package.json\"))),\n )\n const gtkxRoot = dirname(hostingNodeModules)\n console.warn(\"[react-native-gtkx] ensuring gtkx codegen store…\")\n const status = run(\n process.execPath,\n [binOf(fromPackage, \"@gtkx/cli\", \"gtkx\"), \"codegen\"],\n gtkxRoot,\n )\n if (status !== 0) {\n console.error(\n \"[react-native-gtkx] gtkx codegen failed — are GTK4/libadwaita \" +\n \"development files installed?\",\n )\n process.exit(status)\n }\n}\n\nconst bundle = (root: string, entryFile: string, output: string): void => {\n const appRequire = createRequire(join(root, \"package.json\"))\n const status = run(\n process.execPath,\n [\n binOf(appRequire, \"react-native\", \"react-native\"),\n \"bundle\",\n \"--platform\",\n \"linux\",\n \"--dev\",\n \"false\",\n \"--entry-file\",\n entryFile,\n \"--bundle-output\",\n output,\n ],\n root,\n )\n if (status !== 0) {\n process.exit(status)\n }\n}\n\nconst isMetroRunning = async (server: string): Promise<boolean> => {\n try {\n const response = await fetch(`${server}/status`)\n return (await response.text()).includes(\"packager-status:running\")\n } catch {\n return false\n }\n}\n\nconst waitForMetro = async (server: string): Promise<void> => {\n for (let attempt = 0; attempt < 120; attempt += 1) {\n if (await isMetroRunning(server)) {\n return\n }\n await new Promise((resolve) => setTimeout(resolve, 500))\n }\n console.error(\n `[react-native-gtkx] Metro dev server never came up (${server}).`,\n )\n process.exit(1)\n}\n\nlet activeHost: ChildProcess | null = null\n\nconst spawnHost = (\n script: string,\n argument: string,\n cwd: string,\n): Promise<number> =>\n new Promise((resolve) => {\n const hostPath = fileURLToPath(new URL(script, import.meta.url))\n const child = spawn(process.execPath, [hostPath, argument], {\n cwd,\n stdio: \"inherit\",\n })\n activeHost = child\n child.on(\"exit\", (code) => {\n activeHost = null\n resolve(code ?? 1)\n })\n })\n\nconst runLinuxDev = async (\n config: CliConfig,\n args: RunLinuxArgs,\n): Promise<never> => {\n const port = args.port ?? \"8081\"\n const server = `http://localhost:${port}`\n let metro: ChildProcess | null = null\n if (await isMetroRunning(server)) {\n console.warn(\n `[react-native-gtkx] reusing the Metro dev server at ${server}`,\n )\n } else {\n console.warn(\n `[react-native-gtkx] starting the Metro dev server at ${server}…`,\n )\n const appRequire = createRequire(join(config.root, \"package.json\"))\n metro = spawn(\n process.execPath,\n [\n binOf(appRequire, \"react-native\", \"react-native\"),\n \"start\",\n \"--port\",\n port,\n ],\n { cwd: config.root, stdio: \"inherit\" },\n )\n await waitForMetro(server)\n }\n const entry = basename(args.entryFile, extname(args.entryFile))\n const bundleUrl = `${server}/${entry}.bundle?platform=linux&dev=true&minify=false`\n const shutdown = (code: number): never => {\n activeHost?.kill()\n metro?.kill()\n process.exit(code)\n }\n process.on(\"SIGINT\", () => shutdown(0))\n process.on(\"SIGTERM\", () => shutdown(0))\n // Supervisor: a full-refresh request restarts the host with the window\n // reopening on the fresh bundle; any other exit ends the session.\n for (;;) {\n const code = await spawnHost(\"./host-dev.js\", bundleUrl, config.root)\n if (code !== FULL_REFRESH_EXIT_CODE) {\n shutdown(code)\n }\n console.warn(\"[react-native-gtkx] restarting the app after a full refresh…\")\n }\n}\n\nconst runLinux = async (\n _argv: string[],\n config: CliConfig,\n args: RunLinuxArgs,\n): Promise<void> => {\n ensureCodegenStore()\n if (args.dev) {\n await runLinuxDev(config, args)\n return\n }\n const output =\n args.bundleOutput ??\n join(config.root, \"node_modules\", \".react-native-gtkx\", \"main.jsbundle\")\n if (!args.skipBundling) {\n mkdirSync(dirname(output), { recursive: true })\n bundle(config.root, args.entryFile, output)\n }\n const status = await spawnHost(\"./host.js\", output, config.root)\n process.exit(status)\n}\n\n/** Commands contributed to the RN CLI by the package's react-native.config.js. */\nexport const commands = [\n {\n name: \"run-linux\",\n description:\n \"Bundle the app with Metro for the linux platform and run it in the Node+GTK host\",\n options: [\n {\n name: \"--entry-file <path>\",\n description: \"Path to the app entry file\",\n default: \"index.js\",\n },\n {\n name: \"--bundle-output <path>\",\n description:\n \"Where to write the jsbundle (default: node_modules/.react-native-gtkx/main.jsbundle)\",\n },\n {\n name: \"--skip-bundling\",\n description: \"Reuse the existing bundle at --bundle-output\",\n },\n {\n name: \"--dev\",\n description:\n \"Development mode: Metro dev server + Fast Refresh (edits apply to the live window)\",\n },\n {\n name: \"--port <number>\",\n description: \"Metro dev server port for --dev (default: 8081)\",\n },\n ],\n func: runLinux,\n },\n]\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runner/index.ts"],"names":[],"mappings":"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","sourcesContent":["// The `run-linux` CLI command (registered through the package's\n// react-native.config.js, the react-native-windows model): ensure the gtkx\n// codegen store, then either build a release jsbundle with Metro and run\n// it in the Node+GTK host (./host.ts), or — with --dev — start/reuse a\n// Metro dev server and supervise the DEV host (./host-dev.ts): Fast\n// Refresh applies edits to the live window, and a full-refresh request\n// (exit code 65) restarts the host process.\n//\n// Like the hosts, this module must stay runnable under bare Node:\n// builtins and bare specifiers only.\nimport { spawn, spawnSync, type ChildProcess } from \"node:child_process\"\nimport { mkdirSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\nimport { basename, dirname, extname, join } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\nconst fromPackage = createRequire(import.meta.url)\n\ntype CliConfig = { root: string }\ntype RunLinuxArgs = {\n entryFile: string\n bundleOutput?: string\n skipBundling?: boolean\n dev?: boolean\n port?: string\n}\n\n/** Exit code host-dev.ts uses to request a supervisor restart. */\nconst FULL_REFRESH_EXIT_CODE = 65\n\nconst run = (command: string, args: string[], cwd: string): number => {\n const result = spawnSync(command, args, { cwd, stdio: \"inherit\" })\n return result.status ?? 1\n}\n\n/** Resolve an executable script shipped by a dependency's bin field. */\nconst binOf = (\n requireFrom: NodeJS.Require,\n packageName: string,\n binName: string,\n): string => {\n const packageJsonPath = requireFrom.resolve(`${packageName}/package.json`)\n const manifest = requireFrom(`${packageName}/package.json`) as {\n bin?: string | Record<string, string>\n }\n const bin =\n typeof manifest.bin === \"string\" ? manifest.bin : manifest.bin?.[binName]\n if (!bin) {\n throw new Error(`${packageName} does not expose a \"${binName}\" binary`)\n }\n return join(dirname(packageJsonPath), bin)\n}\n\n// RC2-WORKAROUND(codegen-cwd): see docs/gtkx-rc2-notes.md\n// The codegen store lives in the node_modules that hosts the @gtkx\n// packages — run the gtkx CLI from the project that OWNS that node_modules:\n// with cwd inside node_modules itself the CLI reports \"bindings up to date\"\n// without ever creating the store.\nconst ensureCodegenStore = (): void => {\n const hostingNodeModules = dirname(\n dirname(dirname(fromPackage.resolve(\"@gtkx/react/package.json\"))),\n )\n const gtkxRoot = dirname(hostingNodeModules)\n console.warn(\"[react-native-gtkx] ensuring gtkx codegen store…\")\n const status = run(\n process.execPath,\n [binOf(fromPackage, \"@gtkx/cli\", \"gtkx\"), \"codegen\"],\n gtkxRoot,\n )\n if (status !== 0) {\n console.error(\n \"[react-native-gtkx] gtkx codegen failed — are GTK4/libadwaita \" +\n \"development files installed?\",\n )\n process.exit(status)\n }\n}\n\nconst bundle = (root: string, entryFile: string, output: string): void => {\n const appRequire = createRequire(join(root, \"package.json\"))\n const status = run(\n process.execPath,\n [\n binOf(appRequire, \"react-native\", \"react-native\"),\n \"bundle\",\n \"--platform\",\n \"linux\",\n \"--dev\",\n \"false\",\n \"--entry-file\",\n entryFile,\n \"--bundle-output\",\n output,\n ],\n root,\n )\n if (status !== 0) {\n process.exit(status)\n }\n}\n\nconst isMetroRunning = async (server: string): Promise<boolean> => {\n try {\n const response = await fetch(`${server}/status`)\n return (await response.text()).includes(\"packager-status:running\")\n } catch {\n return false\n }\n}\n\nconst waitForMetro = async (server: string): Promise<void> => {\n for (let attempt = 0; attempt < 120; attempt += 1) {\n if (await isMetroRunning(server)) {\n return\n }\n await new Promise((resolve) => setTimeout(resolve, 500))\n }\n console.error(\n `[react-native-gtkx] Metro dev server never came up (${server}).`,\n )\n process.exit(1)\n}\n\nlet activeHost: ChildProcess | null = null\n\nconst spawnHost = (\n script: string,\n argument: string,\n cwd: string,\n): Promise<number> =>\n new Promise((resolve) => {\n // join over `new URL(script, import.meta.url)`: the global URL and the\n // node:url URL come from different type copies when the dependency tree\n // splits @types/node, and the two structurally diverge.\n const hostPath = join(dirname(fileURLToPath(import.meta.url)), script)\n const child = spawn(process.execPath, [hostPath, argument], {\n cwd,\n stdio: \"inherit\",\n })\n activeHost = child\n child.on(\"exit\", (code) => {\n activeHost = null\n resolve(code ?? 1)\n })\n })\n\nconst runLinuxDev = async (\n config: CliConfig,\n args: RunLinuxArgs,\n): Promise<never> => {\n const port = args.port ?? \"8081\"\n const server = `http://localhost:${port}`\n let metro: ChildProcess | null = null\n if (await isMetroRunning(server)) {\n console.warn(\n `[react-native-gtkx] reusing the Metro dev server at ${server}`,\n )\n } else {\n console.warn(\n `[react-native-gtkx] starting the Metro dev server at ${server}…`,\n )\n const appRequire = createRequire(join(config.root, \"package.json\"))\n metro = spawn(\n process.execPath,\n [\n binOf(appRequire, \"react-native\", \"react-native\"),\n \"start\",\n \"--port\",\n port,\n ],\n { cwd: config.root, stdio: \"inherit\" },\n )\n await waitForMetro(server)\n }\n const entry = basename(args.entryFile, extname(args.entryFile))\n const bundleUrl = `${server}/${entry}.bundle?platform=linux&dev=true&minify=false`\n const shutdown = (code: number): never => {\n activeHost?.kill()\n metro?.kill()\n process.exit(code)\n }\n process.on(\"SIGINT\", () => shutdown(0))\n process.on(\"SIGTERM\", () => shutdown(0))\n // Supervisor: a full-refresh request restarts the host with the window\n // reopening on the fresh bundle; any other exit ends the session.\n for (;;) {\n const code = await spawnHost(\"./host-dev.js\", bundleUrl, config.root)\n if (code !== FULL_REFRESH_EXIT_CODE) {\n shutdown(code)\n }\n console.warn(\"[react-native-gtkx] restarting the app after a full refresh…\")\n }\n}\n\nconst runLinux = async (\n _argv: string[],\n config: CliConfig,\n args: RunLinuxArgs,\n): Promise<void> => {\n ensureCodegenStore()\n if (args.dev) {\n await runLinuxDev(config, args)\n return\n }\n const output =\n args.bundleOutput ??\n join(config.root, \"node_modules\", \".react-native-gtkx\", \"main.jsbundle\")\n if (!args.skipBundling) {\n mkdirSync(dirname(output), { recursive: true })\n bundle(config.root, args.entryFile, output)\n }\n const status = await spawnHost(\"./host.js\", output, config.root)\n process.exit(status)\n}\n\n/** Commands contributed to the RN CLI by the package's react-native.config.js. */\nexport const commands = [\n {\n name: \"run-linux\",\n description:\n \"Bundle the app with Metro for the linux platform and run it in the Node+GTK host\",\n options: [\n {\n name: \"--entry-file <path>\",\n description: \"Path to the app entry file\",\n default: \"index.js\",\n },\n {\n name: \"--bundle-output <path>\",\n description:\n \"Where to write the jsbundle (default: node_modules/.react-native-gtkx/main.jsbundle)\",\n },\n {\n name: \"--skip-bundling\",\n description: \"Reuse the existing bundle at --bundle-output\",\n },\n {\n name: \"--dev\",\n description:\n \"Development mode: Metro dev server + Fast Refresh (edits apply to the live window)\",\n },\n {\n name: \"--port <number>\",\n description: \"Metro dev server port for --dev (default: 8081)\",\n },\n ],\n func: runLinux,\n },\n]\n"]}
@@ -245,7 +245,9 @@ const hslToRgb = (h, s, l) => {
245
245
  const chroma = (1 - Math.abs(2 * l - 1)) * s;
246
246
  const hh = h / 60;
247
247
  const x = chroma * (1 - Math.abs((hh % 2) - 1));
248
- let rgb = [0, 0, 0];
248
+ // Every branch assigns, so the sextant picks the triple outright — the
249
+ // placeholder initialiser it used to start from was dead.
250
+ let rgb;
249
251
  if (hh < 1) {
250
252
  rgb = [chroma, x, 0];
251
253
  }