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

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 (85) hide show
  1. package/README.md +4 -5
  2. package/dist/apis/back-handler.d.ts +9 -0
  3. package/dist/apis/back-handler.js +30 -0
  4. package/dist/apis/back-handler.js.map +1 -0
  5. package/dist/apis/host.d.ts +7 -1
  6. package/dist/apis/host.gtkx.js +12 -1
  7. package/dist/apis/host.gtkx.js.map +1 -1
  8. package/dist/apis/host.js.map +1 -1
  9. package/dist/apis/i18n-manager.d.ts +14 -0
  10. package/dist/apis/i18n-manager.js +20 -0
  11. package/dist/apis/i18n-manager.js.map +1 -0
  12. package/dist/apis/index.d.ts +17 -0
  13. package/dist/apis/index.js +5 -0
  14. package/dist/apis/index.js.map +1 -1
  15. package/dist/apis/interaction-manager.d.ts +16 -0
  16. package/dist/apis/interaction-manager.js +96 -0
  17. package/dist/apis/interaction-manager.js.map +1 -0
  18. package/dist/apis/linking.d.ts +4 -0
  19. package/dist/apis/linking.js +9 -0
  20. package/dist/apis/linking.js.map +1 -1
  21. package/dist/components/app-registry.d.ts +2 -0
  22. package/dist/components/app-registry.js +19 -2
  23. package/dist/components/app-registry.js.map +1 -1
  24. package/dist/components/flat-list.d.ts +2 -0
  25. package/dist/components/flat-list.js.map +1 -1
  26. package/dist/components/index.d.ts +1 -1
  27. package/dist/components/index.js +1 -1
  28. package/dist/components/index.js.map +1 -1
  29. package/dist/components/modal.d.ts +1 -1
  30. package/dist/components/root.d.ts +10 -1
  31. package/dist/components/root.js +39 -1
  32. package/dist/components/root.js.map +1 -1
  33. package/dist/components/scroll-view.js +58 -5
  34. package/dist/components/scroll-view.js.map +1 -1
  35. package/dist/components/text-input.d.ts +1 -0
  36. package/dist/components/text-input.js +31 -3
  37. package/dist/components/text-input.js.map +1 -1
  38. package/dist/components/use-layout-child.d.ts +1 -1
  39. package/dist/components/use-layout-child.js +22 -2
  40. package/dist/components/use-layout-child.js.map +1 -1
  41. package/dist/components/virtualized-list.d.ts +2 -0
  42. package/dist/components/virtualized-list.js +132 -10
  43. package/dist/components/virtualized-list.js.map +1 -1
  44. package/dist/gtkx/bridge/index.d.ts +4 -2
  45. package/dist/gtkx/bridge/index.js +6 -2
  46. package/dist/gtkx/bridge/index.js.map +1 -1
  47. package/dist/gtkx/bridge/measure.js +5 -0
  48. package/dist/gtkx/bridge/measure.js.map +1 -1
  49. package/dist/gtkx/bridge/use-signal.d.ts +2 -0
  50. package/dist/gtkx/bridge/use-signal.js +30 -0
  51. package/dist/gtkx/bridge/use-signal.js.map +1 -0
  52. package/dist/index.d.ts +2 -2
  53. package/dist/index.js +2 -2
  54. package/dist/index.js.map +1 -1
  55. package/dist/layout/engine.d.ts +4 -0
  56. package/dist/layout/engine.js +97 -5
  57. package/dist/layout/engine.js.map +1 -1
  58. package/dist/layout/node.d.ts +1 -1
  59. package/dist/layout/node.js +8 -5
  60. package/dist/layout/node.js.map +1 -1
  61. package/dist/metro/index.js +1 -0
  62. package/dist/metro/index.js.map +1 -1
  63. package/dist/navigation/index.d.ts +44 -0
  64. package/dist/navigation/index.js +216 -0
  65. package/dist/navigation/index.js.map +1 -0
  66. package/dist/navigation/option-warnings.d.ts +2 -0
  67. package/dist/navigation/option-warnings.js +61 -0
  68. package/dist/navigation/option-warnings.js.map +1 -0
  69. package/dist/navigation/sidebar.d.ts +37 -0
  70. package/dist/navigation/sidebar.js +71 -0
  71. package/dist/navigation/sidebar.js.map +1 -0
  72. package/dist/perf.d.ts +9 -0
  73. package/dist/perf.js +156 -0
  74. package/dist/perf.js.map +1 -0
  75. package/dist/runner/host-dev.js +15 -6
  76. package/dist/runner/host-dev.js.map +1 -1
  77. package/dist/runner/host.js +24 -9
  78. package/dist/runner/host.js.map +1 -1
  79. package/dist/runner/index.js +4 -1
  80. package/dist/runner/index.js.map +1 -1
  81. package/dist/vite/index.d.ts +5 -4
  82. package/dist/vite/index.js +41 -7
  83. package/dist/vite/index.js.map +1 -1
  84. package/package.json +18 -10
  85. package/types.d.ts +13 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"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","sourcesContent":["// react-native-gtkx/vite — makes a gtkx project React Native compatible.\n// The gtkx CLI (dev and build) starts vite with an inline config that never\n// sets `configFile: false`, so vite picks up the project's vite.config.ts\n// from the root and merges it beneath the CLI config; this preset plugs in\n// there as a single plugin.\n//\n// Single self-contained file on purpose: vite loads the config's imported\n// packages with BARE Node, so this subpath (like ./metro and ./runner) must\n// not contain extensionless relative imports — the pure resolution helpers\n// live here rather than in a sibling module.\nimport { existsSync } from \"node:fs\"\nimport { dirname, extname, isAbsolute, resolve } from \"node:path\"\nimport type { Plugin } from \"vite\"\n\n// --- pure resolution logic (unit-tested directly) -----------------------\n\n/** Options shared by the preset factory and the pure resolver helpers. */\nexport type PlatformResolutionOptions = {\n /** Platform suffix priority, most specific first. Default: [\"linux\", \"native\"]. */\n platforms?: readonly string[]\n /** Source extensions tried for every platform suffix. Default: [\"tsx\", \"ts\", \"jsx\", \"js\"]. */\n extensions?: readonly string[]\n}\n\n/** Predicate the plugin injects as fs.existsSync; tests inject fakes. */\nexport type FileExists = (filePath: string) => boolean\n\nexport const DEFAULT_PLATFORMS: readonly string[] = [\"linux\", \"native\"]\nexport const DEFAULT_EXTENSIONS: readonly string[] = [\"tsx\", \"ts\", \"jsx\", \"js\"]\n\nconst REACT_NATIVE = \"react-native\"\nconst REACT_NATIVE_GTKX = \"react-native-gtkx\"\n\n/**\n * Maps `react-native` (and its subpaths) to `react-native-gtkx`.\n * Returns null for every other specifier, including `react-native-gtkx`\n * itself and lookalikes such as `react-native-web`.\n */\nexport const rewriteReactNativeImport = (source: string): string | null => {\n if (source === REACT_NATIVE) {\n return REACT_NATIVE_GTKX\n }\n if (source.startsWith(`${REACT_NATIVE}/`)) {\n return `${REACT_NATIVE_GTKX}${source.slice(REACT_NATIVE.length)}`\n }\n return null\n}\n\n/** Splits a vite specifier into its path part and its `?query` suffix. */\nexport const splitQuery = (\n source: string,\n): { specifier: string; query: string } => {\n const index = source.indexOf(\"?\")\n if (index === -1) {\n return { specifier: source, query: \"\" }\n }\n return { specifier: source.slice(0, index), query: source.slice(index) }\n}\n\nconst isRelative = (specifier: string): boolean =>\n specifier.startsWith(\"./\") || specifier.startsWith(\"../\")\n\n/**\n * Ordered platform suffixes, platform-major: every extension of the first\n * platform is tried before any extension of the next one\n * (`.linux.tsx`, `.linux.ts`, …, `.native.tsx`, …).\n */\nexport const platformSuffixes = (\n options: PlatformResolutionOptions = {},\n): string[] => {\n const platforms = options.platforms ?? DEFAULT_PLATFORMS\n const extensions = options.extensions ?? DEFAULT_EXTENSIONS\n return platforms.flatMap((platform) =>\n extensions.map((extension) => `.${platform}.${extension}`),\n )\n}\n\n/**\n * Candidate file paths for an extensionless base path, in priority order:\n * direct platform files first, then platform index files of a directory —\n * mirroring Metro, which exhausts file resolution before directory resolution.\n * The base file itself is not a candidate: when no platform file exists the\n * plugin bails out and the default resolver picks the base module.\n */\nexport const platformCandidates = (\n base: string,\n options: PlatformResolutionOptions = {},\n): string[] => {\n const suffixes = platformSuffixes(options)\n return [\n ...suffixes.map((suffix) => `${base}${suffix}`),\n ...suffixes.map((suffix) => `${base}/index${suffix}`),\n ]\n}\n\n/**\n * Metro platform-extension resolution for a single import:\n * only extensionless relative (or absolute) specifiers participate; the first\n * existing candidate wins; the `?query` suffix is carried over. Returns null\n * when the import is out of scope or no platform file exists, handing the\n * import back to the default resolver.\n */\nexport const resolvePlatformSpecifier = (\n source: string,\n importer: string | undefined,\n exists: FileExists,\n options: PlatformResolutionOptions = {},\n): string | null => {\n if (importer === undefined || source.startsWith(\"\\0\")) {\n return null\n }\n const { specifier, query } = splitQuery(source)\n if (!isRelative(specifier) && !isAbsolute(specifier)) {\n return null\n }\n if (extname(specifier) !== \"\") {\n return null\n }\n const base = isAbsolute(specifier)\n ? specifier\n : resolve(dirname(splitQuery(importer).specifier), specifier)\n for (const candidate of platformCandidates(base, options)) {\n if (exists(candidate)) {\n return candidate + query\n }\n }\n return null\n}\n\n// --- the vite plugin ----------------------------------------------------\n\nexport type ReactNativeGtkxOptions = PlatformResolutionOptions\n\n/**\n * Vite plugin: aliases `react-native` (and subpaths) to `react-native-gtkx`\n * and resolves Metro-style platform extensions\n * (`.linux.tsx` → `.native.tsx` → base) for extensionless imports.\n */\nexport const reactNativeGtkx = (\n options: ReactNativeGtkxOptions = {},\n): Plugin => ({\n name: \"react-native-gtkx:preset\",\n // Before vite's own resolver and the gtkx CLI plugins: the alias must win\n // over node resolution and platform files must win over the base file.\n enforce: \"pre\",\n\n config: () => ({\n ssr: {\n // `gtkx dev` runs vite with ssr.external: true, which would hand\n // react-native-gtkx straight to node. Keep the package inside the\n // vite pipeline; noExternal wins over external: true.\n //\n // \"react-native\" must be listed too: with ssr.external: true vite\n // externalizes a bare import BEFORE the plugin pipeline whenever the\n // package resolves natively — and the real react-native (a Flow\n // codebase Node cannot parse) exists in RN monorepos. noExternal\n // forces the full plugin resolution, where the alias rewrites the\n // import to react-native-gtkx.\n noExternal: [\"react-native-gtkx\", \"react-native\"],\n },\n }),\n\n async resolveId(source, importer) {\n const aliased = rewriteReactNativeImport(source)\n if (aliased !== null) {\n const resolved = await this.resolve(aliased, importer, { skipSelf: true })\n return resolved ?? aliased\n }\n return resolvePlatformSpecifier(source, importer, existsSync, options)\n },\n})\n\nexport default reactNativeGtkx\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"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","sourcesContent":["// react-native-gtkx/vite — makes a gtkx project React Native compatible.\n// The gtkx CLI (dev and build) starts vite with an inline config that never\n// sets `configFile: false`, so vite picks up the project's vite.config.ts\n// from the root and merges it beneath the CLI config; this preset plugs in\n// there as a single plugin.\n//\n// Single self-contained file on purpose: vite loads the config's imported\n// packages with BARE Node, so this subpath (like ./metro and ./runner) must\n// not contain extensionless relative imports — the pure resolution helpers\n// live here rather than in a sibling module.\nimport { existsSync } from \"node:fs\"\nimport { dirname, extname, isAbsolute, resolve } from \"node:path\"\nimport type { Plugin } from \"vite\"\n\n// --- pure resolution logic (unit-tested directly) -----------------------\n\n/** Options shared by the preset factory and the pure resolver helpers. */\nexport type PlatformResolutionOptions = {\n /** Platform suffix priority, most specific first. Default: [\"linux\", \"native\"]. */\n platforms?: readonly string[]\n /** Source extensions tried for every platform suffix. Default: [\"tsx\", \"ts\", \"jsx\", \"js\"]. */\n extensions?: readonly string[]\n}\n\n/** Predicate the plugin injects as fs.existsSync; tests inject fakes. */\nexport type FileExists = (filePath: string) => boolean\n\nexport const DEFAULT_PLATFORMS: readonly string[] = [\"linux\", \"native\"]\nexport const DEFAULT_EXTENSIONS: readonly string[] = [\"tsx\", \"ts\", \"jsx\", \"js\"]\n\nconst REACT_NATIVE = \"react-native\"\nconst REACT_NATIVE_GTKX = \"react-native-gtkx\"\n\n/**\n * Maps `react-native` (and its subpaths) to `react-native-gtkx`.\n * Returns null for every other specifier, including `react-native-gtkx`\n * itself and lookalikes such as `react-native-web`.\n */\nexport const rewriteReactNativeImport = (source: string): string | null => {\n if (source === REACT_NATIVE) {\n return REACT_NATIVE_GTKX\n }\n if (source.startsWith(`${REACT_NATIVE}/`)) {\n return `${REACT_NATIVE_GTKX}${source.slice(REACT_NATIVE.length)}`\n }\n return null\n}\n\n/** Splits a vite specifier into its path part and its `?query` suffix. */\nexport const splitQuery = (\n source: string,\n): { specifier: string; query: string } => {\n const index = source.indexOf(\"?\")\n if (index === -1) {\n return { specifier: source, query: \"\" }\n }\n return { specifier: source.slice(0, index), query: source.slice(index) }\n}\n\nconst isRelative = (specifier: string): boolean =>\n specifier.startsWith(\"./\") || specifier.startsWith(\"../\")\n\n/**\n * Ordered platform suffixes, platform-major: every extension of the first\n * platform is tried before any extension of the next one\n * (`.linux.tsx`, `.linux.ts`, …, `.native.tsx`, …).\n */\nexport const platformSuffixes = (\n options: PlatformResolutionOptions = {},\n): string[] => {\n const platforms = options.platforms ?? DEFAULT_PLATFORMS\n const extensions = options.extensions ?? DEFAULT_EXTENSIONS\n return platforms.flatMap((platform) =>\n extensions.map((extension) => `.${platform}.${extension}`),\n )\n}\n\n/**\n * Candidate file paths for an extensionless base path, in priority order:\n * direct platform files first, then platform index files of a directory —\n * mirroring Metro, which exhausts file resolution before directory resolution.\n * The base file itself is not a candidate: when no platform file exists the\n * plugin bails out and the default resolver picks the base module.\n */\nexport const platformCandidates = (\n base: string,\n options: PlatformResolutionOptions = {},\n): string[] => {\n const suffixes = platformSuffixes(options)\n return [\n ...suffixes.map((suffix) => `${base}${suffix}`),\n ...suffixes.map((suffix) => `${base}/index${suffix}`),\n ]\n}\n\n// Source extensions Metro strips before trying platform variants: an\n// import of \"./useLinking.js\" (the TS-ESM style react-navigation and most\n// compiled RN libraries use) must still find useLinking.native.tsx /\n// useLinking.native.js — Metro resolves the BASE name platform-first, the\n// literal file is only the fallback.\nconst STRIPPABLE_EXTENSIONS = new Set([\".js\", \".jsx\", \".mjs\", \".ts\", \".tsx\"])\n\n/**\n * Metro platform-extension resolution for a single import: relative (or\n * absolute) specifiers that are extensionless — or carry a strippable\n * source extension — try platform candidates first; the first existing\n * candidate wins; the `?query` suffix is carried over. Returns null when\n * the import is out of scope or no platform file exists, handing the\n * import back to the default resolver.\n */\nexport const resolvePlatformSpecifier = (\n source: string,\n importer: string | undefined,\n exists: FileExists,\n options: PlatformResolutionOptions = {},\n): string | null => {\n if (importer === undefined || source.startsWith(\"\\0\")) {\n return null\n }\n const { specifier, query } = splitQuery(source)\n if (!isRelative(specifier) && !isAbsolute(specifier)) {\n return null\n }\n const extension = extname(specifier)\n if (extension !== \"\" && !STRIPPABLE_EXTENSIONS.has(extension)) {\n return null\n }\n const withExtension = isAbsolute(specifier)\n ? specifier\n : resolve(dirname(splitQuery(importer).specifier), specifier)\n const base =\n extension === \"\" ? withExtension : withExtension.slice(0, -extension.length)\n for (const candidate of platformCandidates(base, options)) {\n if (exists(candidate)) {\n return candidate + query\n }\n }\n return null\n}\n\n// --- the vite plugin ----------------------------------------------------\n\nexport type ReactNativeGtkxOptions = PlatformResolutionOptions\n\n/**\n * Vite plugin: aliases `react-native` (and subpaths) to `react-native-gtkx`\n * and resolves Metro-style platform extensions\n * (`.linux.tsx` → `.native.tsx` → base) for extensionless imports.\n */\nexport const reactNativeGtkx = (\n options: ReactNativeGtkxOptions = {},\n): Plugin => ({\n name: \"react-native-gtkx:preset\",\n // Before vite's own resolver and the gtkx CLI plugins: the alias must win\n // over node resolution and platform files must win over the base file.\n enforce: \"pre\",\n\n config: () => ({\n ssr: {\n // `gtkx dev` runs vite with ssr.external: true, which would hand\n // react-native-gtkx straight to node. Keep the package inside the\n // vite pipeline; noExternal wins over external: true.\n //\n // \"react-native\" must be listed too: with ssr.external: true vite\n // externalizes a bare import BEFORE the plugin pipeline whenever the\n // package resolves natively — and the real react-native (a Flow\n // codebase Node cannot parse) exists in RN monorepos. noExternal\n // forces the full plugin resolution, where the alias rewrites the\n // import to react-native-gtkx.\n // @react-navigation must go through the pipeline too: it imports\n // \"react-native\", and an externalized copy resolves that to the real\n // Flow package (SyntaxError: Unexpected token 'typeof') instead of\n // our alias. Only bites on the dev path — a production build inlines\n // everything anyway.\n noExternal: [\"react-native-gtkx\", \"react-native\", /^@react-navigation\\//],\n },\n resolve: {\n // The gtkx runtime and react are single-instance hosts: when the app\n // and react-native-gtkx resolve them from different node_modules\n // (file:-installed package, nested installs), two bundled copies\n // double-init the runtime and GLib aborts. dedupe pins every copy to\n // the project's own resolution.\n dedupe: [\n \"@gtkx/css\",\n \"@gtkx/gi\",\n \"@gtkx/jsx\",\n \"@gtkx/native\",\n \"@gtkx/react\",\n \"@gtkx/runtime\",\n // react-navigation is context-based: two bundled copies of core\n // fail with \"couldn't find a navigation context\".\n \"@react-navigation/core\",\n \"@react-navigation/native\",\n \"react\",\n ],\n },\n }),\n\n async resolveId(source, importer) {\n const aliased = rewriteReactNativeImport(source)\n if (aliased !== null) {\n const resolved = await this.resolve(aliased, importer, { skipSelf: true })\n return resolved ?? aliased\n }\n return resolvePlatformSpecifier(source, importer, existsSync, options)\n },\n})\n\nexport default reactNativeGtkx\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gtkx",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.3",
4
4
  "description": "React Native components and APIs for Linux desktop, rendered as native GTK4 widgets via gtkx",
5
5
  "license": "MIT",
6
6
  "author": "Anton Petrov <anton@itsmepetrov.com>",
@@ -27,7 +27,7 @@
27
27
  "main": "./dist/index.js",
28
28
  "types": "./dist/index.d.ts",
29
29
  "engines": {
30
- "node": ">=22.15"
30
+ "node": ">=24"
31
31
  },
32
32
  "exports": {
33
33
  "./package.json": "./package.json",
@@ -43,6 +43,10 @@
43
43
  "types": "./dist/runner/index.d.ts",
44
44
  "default": "./dist/runner/index.js"
45
45
  },
46
+ "./navigation": {
47
+ "types": "./dist/navigation/index.d.ts",
48
+ "default": "./dist/navigation/index.js"
49
+ },
46
50
  "./vite": {
47
51
  "types": "./dist/vite/index.d.ts",
48
52
  "default": "./dist/vite/index.js"
@@ -58,25 +62,29 @@
58
62
  "watch:dist": "tsc -p tsconfig.build.json --watch --preserveWatchOutput"
59
63
  },
60
64
  "peerDependencies": {
61
- "react": "^19",
65
+ "@react-navigation/native": "^7.0.0",
66
+ "react": "^19.2",
62
67
  "vite": "^7.0.0 || ^8.0.0"
63
68
  },
64
69
  "peerDependenciesMeta": {
70
+ "@react-navigation/native": {
71
+ "optional": true
72
+ },
65
73
  "vite": {
66
74
  "optional": true
67
75
  }
68
76
  },
69
77
  "dependencies": {
70
- "@gtkx/cli": "1.0.0-rc.1",
71
- "@gtkx/config": "1.0.0-rc.1",
72
- "@gtkx/css": "1.0.0-rc.1",
73
- "@gtkx/react": "1.0.0-rc.1",
74
- "@gtkx/runtime": "1.0.0-rc.1",
78
+ "@gtkx/cli": "1.0.0-rc.2",
79
+ "@gtkx/config": "1.0.0-rc.2",
80
+ "@gtkx/css": "1.0.0-rc.2",
81
+ "@gtkx/react": "1.0.0-rc.2",
82
+ "@gtkx/runtime": "1.0.0-rc.2",
75
83
  "yoga-layout": "^3.2.1"
76
84
  },
77
85
  "devDependencies": {
78
- "@gtkx/testing": "1.0.0-rc.1",
79
- "@gtkx/vitest": "1.0.0-rc.1",
86
+ "@gtkx/testing": "1.0.0-rc.2",
87
+ "@gtkx/vitest": "1.0.0-rc.2",
80
88
  "vite": "^8.1.4"
81
89
  },
82
90
  "files": [
package/types.d.ts CHANGED
@@ -38,6 +38,19 @@ declare module "react-native" {
38
38
  default?: T
39
39
  }): T | undefined
40
40
  }
41
+
42
+ // Desktop has a pointer, so Pressable reports hover alongside press —
43
+ // `style={({ pressed, hovered }) => …}` and the children callback, the
44
+ // same shape react-native-web exposes. The stock type only carries
45
+ // `pressed` (mobile has no hover), and interfaces merge, so referencing
46
+ // this module adds the field without touching anything else.
47
+ //
48
+ // OPTIONAL on purpose: an app sharing one component with ios/android
49
+ // gets `undefined` there, and the type should say so — write
50
+ // `hovered && styles.hovered`, which is correct on every platform.
51
+ interface PressableStateCallbackType {
52
+ hovered?: boolean
53
+ }
41
54
  }
42
55
 
43
56
  export {}