react-native-gtkx 0.1.0-alpha.4 → 0.2.0-alpha.2
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/README.md +22 -9
- package/dist/adw/index.d.ts +3 -0
- package/dist/adw/index.js +41 -0
- package/dist/adw/index.js.map +1 -0
- package/dist/adw/widgets.generated.d.ts +63 -0
- package/dist/adw/widgets.generated.js +125 -0
- package/dist/adw/widgets.generated.js.map +1 -0
- package/dist/animated/create-animated.d.ts +2 -0
- package/dist/animated/create-animated.js +2 -0
- package/dist/animated/create-animated.js.map +1 -1
- package/dist/animated/index.d.ts +2 -0
- package/dist/animated/index.js +1 -0
- package/dist/animated/index.js.map +1 -1
- package/dist/animated/value-xy.d.ts +41 -0
- package/dist/animated/value-xy.js +90 -0
- package/dist/animated/value-xy.js.map +1 -0
- package/dist/animated/value.d.ts +9 -0
- package/dist/animated/value.js +30 -2
- package/dist/animated/value.js.map +1 -1
- package/dist/common/content.d.ts +69 -0
- package/dist/common/content.js +84 -0
- package/dist/common/content.js.map +1 -0
- package/dist/common/icon.d.ts +23 -0
- package/dist/common/icon.js +14 -0
- package/dist/common/icon.js.map +1 -0
- package/dist/common/index.d.ts +5 -0
- package/dist/common/index.js +21 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/list.d.ts +82 -0
- package/dist/common/list.js +166 -0
- package/dist/common/list.js.map +1 -0
- package/dist/common/navigation-stack.d.ts +84 -0
- package/dist/common/navigation-stack.js +313 -0
- package/dist/common/navigation-stack.js.map +1 -0
- package/dist/common/widget.d.ts +62 -0
- package/dist/common/widget.js +209 -0
- package/dist/common/widget.js.map +1 -0
- package/dist/components/animated.d.ts +7 -4
- package/dist/components/animated.js +88 -67
- package/dist/components/animated.js.map +1 -1
- package/dist/components/app-registry.d.ts +36 -1
- package/dist/components/app-registry.js +8 -3
- package/dist/components/app-registry.js.map +1 -1
- package/dist/components/host-node.d.ts +7 -0
- package/dist/components/host-node.js +26 -1
- package/dist/components/host-node.js.map +1 -1
- package/dist/components/index.d.ts +6 -2
- package/dist/components/index.js +2 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/measure.d.ts +13 -0
- package/dist/components/measure.js +51 -0
- package/dist/components/measure.js.map +1 -0
- package/dist/components/modal.d.ts +1 -1
- package/dist/components/press-event.d.ts +28 -0
- package/dist/components/press-event.js +46 -0
- package/dist/components/press-event.js.map +1 -0
- package/dist/components/pressable.d.ts +2 -6
- package/dist/components/pressable.js +119 -20
- package/dist/components/pressable.js.map +1 -1
- package/dist/components/rect-store.d.ts +11 -1
- package/dist/components/rect-store.js +27 -3
- package/dist/components/rect-store.js.map +1 -1
- package/dist/components/scroll-view.d.ts +4 -0
- package/dist/components/scroll-view.js +8 -2
- package/dist/components/scroll-view.js.map +1 -1
- package/dist/components/svg/animated-support.d.ts +19 -0
- package/dist/components/svg/animated-support.js +64 -0
- package/dist/components/svg/animated-support.js.map +1 -0
- package/dist/components/svg/context.d.ts +8 -0
- package/dist/components/svg/context.js +15 -0
- package/dist/components/svg/context.js.map +1 -0
- package/dist/components/svg/gradients.d.ts +31 -0
- package/dist/components/svg/gradients.js +93 -0
- package/dist/components/svg/gradients.js.map +1 -0
- package/dist/components/svg/group.d.ts +8 -0
- package/dist/components/svg/group.js +30 -0
- package/dist/components/svg/group.js.map +1 -0
- package/dist/components/svg/index.d.ts +6 -0
- package/dist/components/svg/index.js +5 -0
- package/dist/components/svg/index.js.map +1 -0
- package/dist/components/svg/node.d.ts +7 -0
- package/dist/components/svg/node.js +7 -0
- package/dist/components/svg/node.js.map +1 -0
- package/dist/components/svg/paint.d.ts +24 -0
- package/dist/components/svg/paint.js +57 -0
- package/dist/components/svg/paint.js.map +1 -0
- package/dist/components/svg/shapes.d.ts +47 -0
- package/dist/components/svg/shapes.js +51 -0
- package/dist/components/svg/shapes.js.map +1 -0
- package/dist/components/svg/svg.d.ts +14 -0
- package/dist/components/svg/svg.js +48 -0
- package/dist/components/svg/svg.js.map +1 -0
- package/dist/components/svg/use-shape-node.d.ts +12 -0
- package/dist/components/svg/use-shape-node.js +52 -0
- package/dist/components/svg/use-shape-node.js.map +1 -0
- package/dist/components/text-input.js +1 -1
- package/dist/components/text-input.js.map +1 -1
- package/dist/components/text.js +36 -3
- package/dist/components/text.js.map +1 -1
- package/dist/components/use-layout-child.js +50 -4
- package/dist/components/use-layout-child.js.map +1 -1
- package/dist/components/view.d.ts +9 -4
- package/dist/components/view.js +8 -2
- package/dist/components/view.js.map +1 -1
- package/dist/contracts.d.ts +31 -4
- package/dist/contracts.js.map +1 -1
- package/dist/gtk/index.d.ts +7 -0
- package/dist/gtk/index.js +46 -0
- package/dist/gtk/index.js.map +1 -0
- package/dist/gtk/widgets.generated.d.ts +103 -0
- package/dist/gtk/widgets.generated.js +205 -0
- package/dist/gtk/widgets.generated.js.map +1 -0
- package/dist/gtk/window-actions.d.ts +77 -0
- package/dist/gtk/window-actions.js +193 -0
- package/dist/gtk/window-actions.js.map +1 -0
- package/dist/gtkx/bridge/geometry.d.ts +15 -0
- package/dist/gtkx/bridge/geometry.js +38 -0
- package/dist/gtkx/bridge/geometry.js.map +1 -0
- package/dist/gtkx/bridge/index.d.ts +11 -4
- package/dist/gtkx/bridge/index.js +47 -6
- package/dist/gtkx/bridge/index.js.map +1 -1
- package/dist/gtkx/bridge/layout-manager.d.ts +2 -1
- package/dist/gtkx/bridge/layout-manager.js +31 -9
- package/dist/gtkx/bridge/layout-manager.js.map +1 -1
- package/dist/gtkx/bridge/slot-portal.d.ts +12 -0
- package/dist/gtkx/bridge/slot-portal.js +17 -0
- package/dist/gtkx/bridge/slot-portal.js.map +1 -0
- package/dist/gtkx/bridge/svg-node.d.ts +79 -0
- package/dist/gtkx/bridge/svg-node.js +323 -0
- package/dist/gtkx/bridge/svg-node.js.map +1 -0
- package/dist/gtkx/bridge/use-signal.js +19 -9
- package/dist/gtkx/bridge/use-signal.js.map +1 -1
- package/dist/gtkx/bridge/widgets.generated.d.ts +2 -0
- package/dist/gtkx/bridge/widgets.generated.js +14 -0
- package/dist/gtkx/bridge/widgets.generated.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/bin.d.ts +2 -0
- package/dist/mcp/bin.js +17 -0
- package/dist/mcp/bin.js.map +1 -0
- package/dist/mcp/data/generated.d.ts +1304 -0
- package/dist/mcp/data/generated.js +1179 -0
- package/dist/mcp/data/generated.js.map +1 -0
- package/dist/mcp/index.d.ts +5 -0
- package/dist/mcp/index.js +9 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/list.d.ts +4 -0
- package/dist/mcp/list.js +56 -0
- package/dist/mcp/list.js.map +1 -0
- package/dist/mcp/resolve.d.ts +55 -0
- package/dist/mcp/resolve.js +151 -0
- package/dist/mcp/resolve.js.map +1 -0
- package/dist/mcp/search.d.ts +13 -0
- package/dist/mcp/search.js +48 -0
- package/dist/mcp/search.js.map +1 -0
- package/dist/mcp/server.d.ts +7 -0
- package/dist/mcp/server.js +135 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tool.d.ts +21 -0
- package/dist/mcp/tool.js +36 -0
- package/dist/mcp/tool.js.map +1 -0
- package/dist/metro/index.js +10 -0
- package/dist/metro/index.js.map +1 -1
- package/dist/navigation/index.d.ts +50 -13
- package/dist/navigation/index.js +183 -148
- package/dist/navigation/index.js.map +1 -1
- package/dist/navigation/option-warnings.js +9 -1
- package/dist/navigation/option-warnings.js.map +1 -1
- package/dist/navigation/sidebar.d.ts +207 -9
- package/dist/navigation/sidebar.js +294 -10
- package/dist/navigation/sidebar.js.map +1 -1
- package/dist/responder/system.d.ts +27 -0
- package/dist/responder/system.js +184 -0
- package/dist/responder/system.js.map +1 -0
- package/dist/responder/touch-history.d.ts +10 -0
- package/dist/responder/touch-history.js +78 -0
- package/dist/responder/touch-history.js.map +1 -0
- package/dist/responder/types.d.ts +63 -0
- package/dist/responder/types.js +29 -0
- package/dist/responder/types.js.map +1 -0
- package/dist/responder/use-responder.d.ts +12 -0
- package/dist/responder/use-responder.js +98 -0
- package/dist/responder/use-responder.js.map +1 -0
- package/dist/runner/host-dev.js +3 -1
- package/dist/runner/host-dev.js.map +1 -1
- package/dist/runner/host.js +5 -1
- package/dist/runner/host.js.map +1 -1
- package/dist/runner/index.d.ts +22 -2
- package/dist/runner/index.js +163 -13
- package/dist/runner/index.js.map +1 -1
- package/dist/sea/assemble.d.ts +29 -0
- package/dist/sea/assemble.js +129 -0
- package/dist/sea/assemble.js.map +1 -0
- package/dist/sea/bundle.d.ts +61 -0
- package/dist/sea/bundle.js +202 -0
- package/dist/sea/bundle.js.map +1 -0
- package/dist/sea/gtkx-config-module.d.ts +18 -0
- package/dist/sea/gtkx-config-module.js +67 -0
- package/dist/sea/gtkx-config-module.js.map +1 -0
- package/dist/sea/native-shim.d.ts +40 -0
- package/dist/sea/native-shim.js +121 -0
- package/dist/sea/native-shim.js.map +1 -0
- package/dist/sea/react-anchor-plugin.d.ts +2 -0
- package/dist/sea/react-anchor-plugin.js +30 -0
- package/dist/sea/react-anchor-plugin.js.map +1 -0
- package/dist/style/box-shadow.d.ts +7 -0
- package/dist/style/box-shadow.js +197 -0
- package/dist/style/box-shadow.js.map +1 -0
- package/dist/style/index.d.ts +3 -0
- package/dist/style/index.js +3 -0
- package/dist/style/index.js.map +1 -1
- package/dist/style/split-style.d.ts +5 -2
- package/dist/style/split-style.js +33 -5
- package/dist/style/split-style.js.map +1 -1
- package/dist/style/text-decoration.d.ts +15 -0
- package/dist/style/text-decoration.js +26 -0
- package/dist/style/text-decoration.js.map +1 -0
- package/dist/style/transform.d.ts +22 -0
- package/dist/style/transform.js +137 -0
- package/dist/style/transform.js.map +1 -0
- package/dist/style/visual-css.js +40 -3
- package/dist/style/visual-css.js.map +1 -1
- package/dist/svg/geometry.d.ts +19 -0
- package/dist/svg/geometry.js +80 -0
- package/dist/svg/geometry.js.map +1 -0
- package/dist/svg/gradient-geometry.d.ts +15 -0
- package/dist/svg/gradient-geometry.js +15 -0
- package/dist/svg/gradient-geometry.js.map +1 -0
- package/dist/svg/transform.d.ts +22 -0
- package/dist/svg/transform.js +74 -0
- package/dist/svg/transform.js.map +1 -0
- package/dist/svg/view-box.d.ts +34 -0
- package/dist/svg/view-box.js +108 -0
- package/dist/svg/view-box.js.map +1 -0
- package/dist/svg-compat/index.d.ts +1 -0
- package/dist/svg-compat/index.js +16 -0
- package/dist/svg-compat/index.js.map +1 -0
- package/dist/testing/index.d.ts +14 -0
- package/dist/testing/index.js +14 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/vendor/react-native/pan-responder.d.ts +102 -0
- package/dist/vendor/react-native/pan-responder.js +196 -0
- package/dist/vendor/react-native/pan-responder.js.map +1 -0
- package/dist/vendor/react-native/touch-history-math.d.ts +18 -0
- package/dist/vendor/react-native/touch-history-math.js +102 -0
- package/dist/vendor/react-native/touch-history-math.js.map +1 -0
- package/dist/vite/index.d.ts +7 -3
- package/dist/vite/index.js +16 -4
- package/dist/vite/index.js.map +1 -1
- package/dist/vitest/index.d.ts +52 -0
- package/dist/vitest/index.js +58 -0
- package/dist/vitest/index.js.map +1 -0
- package/dist/vitest/setup.d.ts +4 -0
- package/dist/vitest/setup.js +22 -0
- package/dist/vitest/setup.js.map +1 -0
- package/package.json +52 -13
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/mcp/tool.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,GAAG,CAAC,IAAY,EAAkB,EAAE,CAAC,CAAC;IACrD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;CAClC,CAAC,CAAA;AAEF,MAAM,SAAS,GAAG,CAAC,IAAY,EAAkB,EAAE,CAAC,CAAC;IACnD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACjC,OAAO,EAAE,IAAI;CACd,CAAC,CAAA;AAEF,MAAM,aAAa,GAAG,CAAC,KAAc,EAAkB,EAAE,CACvD,SAAS,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;AAEnE,MAAM,OAAO,GAAG,CACd,OAAsE,EACtE,IAAyC,EACzB,EAAE;IAClB,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,aAAa,CAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;AACH,CAAC,CAAA;AAED;;sDAEsD;AACtD,MAAM,UAAU,GAAG,CACjB,IAAiB,EACX,EAAE,CAAC,IAAY,CAAA;AAEvB,MAAM,YAAY,GAAG,CAAC,MAAiB,EAAE,IAAU,EAAQ,EAAE;IAC3D,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAyC,EAAE,EAAE,CAC9D,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAA4C,CAAA;IAEzE,MAAM,CAAC,YAAY,CACjB,IAAI,CAAC,IAAI,EACT;QACE,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE;YACX,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,QAAQ,CACT,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EACL,UAAU,EACV,YAAY,EACZ,WAAW,EACX,SAAS,GAGV,CAAA","sourcesContent":["// Small defineTool/registerTool helper over @modelcontextprotocol/sdk's\n// McpServer, in the same spirit as @gtkx/mcp's own src/tool.ts (a sibling\n// package in this monorepo's node_modules, studied as a reference) — but\n// written fresh: this server has no live-app connection to route errors\n// through, so there is no ProtocolError type to special-case, only plain\n// Error.\nimport type {\n McpServer,\n ToolCallback,\n} from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\"\nimport type { z } from \"zod\"\n\ntype ToolArgs<Shape extends Record<string, z.ZodType>> = {\n [K in keyof Shape]: z.output<Shape[K]>\n}\n\ntype Tool<Shape extends Record<string, z.ZodType> = Record<string, z.ZodType>> =\n {\n name: string\n title: string\n description: string\n inputSchema: Shape\n handler: (args: ToolArgs<Shape>) => CallToolResult\n }\n\nconst textContent = (text: string): CallToolResult => ({\n content: [{ type: \"text\", text }],\n})\n\nconst textError = (text: string): CallToolResult => ({\n content: [{ type: \"text\", text }],\n isError: true,\n})\n\nconst errorToResult = (error: unknown): CallToolResult =>\n textError(error instanceof Error ? error.message : String(error))\n\nconst runTool = (\n handler: (args: ToolArgs<Record<string, z.ZodType>>) => CallToolResult,\n args: ToolArgs<Record<string, z.ZodType>>,\n): CallToolResult => {\n try {\n return handler(args)\n } catch (error) {\n return errorToResult(error)\n }\n}\n\n/** Identity function with a narrower input type — keeps tool definitions\n * readable (named fields) while erasing the generic Shape at the call site,\n * matching the pattern registerTool below expects. */\nconst defineTool = <Shape extends Record<string, z.ZodType>>(\n tool: Tool<Shape>,\n): Tool => tool as Tool\n\nconst registerTool = (server: McpServer, tool: Tool): void => {\n const callback = ((args: ToolArgs<Record<string, z.ZodType>>) =>\n runTool(tool.handler, args)) as ToolCallback<Record<string, z.ZodType>>\n\n server.registerTool(\n tool.name,\n {\n title: tool.title,\n description: tool.description,\n inputSchema: tool.inputSchema,\n annotations: {\n title: tool.title,\n readOnlyHint: true,\n destructiveHint: false,\n openWorldHint: false,\n },\n },\n callback,\n )\n}\n\nexport {\n defineTool,\n registerTool,\n textContent,\n textError,\n type Tool,\n type ToolArgs,\n}\n"]}
|
package/dist/metro/index.js
CHANGED
|
@@ -31,11 +31,13 @@ export const HOST_MODULE_EXTERNALS = [
|
|
|
31
31
|
"@gtkx/gi/gdk",
|
|
32
32
|
"@gtkx/gi/gio",
|
|
33
33
|
"@gtkx/gi/glib",
|
|
34
|
+
"@gtkx/gi/gobject",
|
|
34
35
|
"@gtkx/gi/graphene",
|
|
35
36
|
"@gtkx/gi/gsk",
|
|
36
37
|
"@gtkx/gi/gtk",
|
|
37
38
|
"@gtkx/gi/pango",
|
|
38
39
|
"@gtkx/jsx/adw",
|
|
40
|
+
"@gtkx/jsx/gio",
|
|
39
41
|
"@gtkx/jsx/gtk",
|
|
40
42
|
"@gtkx/react",
|
|
41
43
|
"@gtkx/react/internal",
|
|
@@ -96,6 +98,14 @@ export const withLinuxPlatform = (config, options = {}) => {
|
|
|
96
98
|
moduleName.startsWith("react-native/")) {
|
|
97
99
|
return fallback(context, moduleName.replace(/^react-native/, "react-native-gtkx"), platform);
|
|
98
100
|
}
|
|
101
|
+
// Same alias, same guard shape, for the SVG compat subpath (see
|
|
102
|
+
// src/svg-compat/index.ts and the vite preset's rewriteReactNativeImport
|
|
103
|
+
// — kept in sync deliberately rather than sharing code, Metro and vite
|
|
104
|
+
// resolvers have never shared an implementation in this package).
|
|
105
|
+
if (moduleName === "react-native-svg" ||
|
|
106
|
+
moduleName.startsWith("react-native-svg/")) {
|
|
107
|
+
return fallback(context, moduleName.replace(/^react-native-svg/, "react-native-gtkx/svg"), platform);
|
|
108
|
+
}
|
|
99
109
|
return fallback(context, moduleName, platform);
|
|
100
110
|
};
|
|
101
111
|
// The cast: T may carry narrower resolver/serializer types than the ones
|
package/dist/metro/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metro/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Metro preset for the linux out-of-tree platform: wrap the app's Metro\n// config with `withLinuxPlatform` and the standard RN toolchain bundles for\n// `--platform linux`.\n//\n// What it does on top of RN defaults (validated by spike/rn-platform):\n//\n// 1. Adds \"linux\" to resolver.platforms (`.linux.tsx` extensions and\n// Platform.OS come along with it).\n// 2. Redirects `react-native` (and subpaths) to `react-native-gtkx` — the\n// out-of-tree npmPackageName declaration alone does not alias imports\n// for `bundle`, the resolver has to.\n// 3. EXTERNALIZES host-side singletons. Unlike react-native-windows, whose\n// native side lives outside the JS bundle by construction, our \"native\"\n// is Node modules with NAPI bindings (@gtkx/*) plus yoga-layout's WASM —\n// Metro cannot bundle those. react (and its jsx runtimes) must also stay\n// host-side: the reconciler inside @gtkx/react and the app have to share\n// one React instance. Every external resolves to a generated proxy that\n// reads the real module from global.__hostModules — the run-linux host\n// injects them before executing the bundle.\n// 4. Proxies Node builtins through the host's require: apps on this\n// platform may use the whole Node API, it is a platform feature.\n// 5. Drops InitializeCore (RN's mobile environment polyfills): the runtime\n// environment IS Node, the host provides everything.\nimport { mkdirSync, writeFileSync } from \"node:fs\"\nimport { builtinModules, isBuiltin } from \"node:module\"\nimport { join } from \"node:path\"\n\n/** Modules the run-linux host provides to the bundle at runtime. */\nexport const HOST_MODULE_EXTERNALS = [\n \"@gtkx/css\",\n \"@gtkx/gi/adw\",\n \"@gtkx/gi/gdk\",\n \"@gtkx/gi/gio\",\n \"@gtkx/gi/glib\",\n \"@gtkx/gi/graphene\",\n \"@gtkx/gi/gsk\",\n \"@gtkx/gi/gtk\",\n \"@gtkx/gi/pango\",\n \"@gtkx/jsx/adw\",\n \"@gtkx/jsx/gtk\",\n \"@gtkx/react\",\n \"@gtkx/react/internal\",\n \"@gtkx/runtime\",\n \"react\",\n \"react/jsx-runtime\",\n \"react/jsx-dev-runtime\",\n \"yoga-layout\",\n]\n\nexport const LINUX_PLATFORM = \"linux\"\n\n// Structural slices of Metro's config/resolution types: Metro is the app's\n// dependency, not ours — depending on its types here would pin versions.\nexport type MetroResolutionContext = {\n resolveRequest: MetroResolver\n}\nexport type MetroResolution = { type: string; filePath?: string }\nexport type MetroResolver = (\n context: MetroResolutionContext,\n moduleName: string,\n platform: string | null,\n) => MetroResolution\n\nexport type MetroLikeConfig = {\n projectRoot?: string\n resolver?: {\n platforms?: readonly string[]\n resolveRequest?: MetroResolver | null\n }\n serializer?: {\n getModulesRunBeforeMainModule?: (entryFilePath: string) => string[]\n }\n}\n\nexport type LinuxPlatformOptions = {\n /** Extra host-provided modules to keep out of the bundle. */\n externals?: readonly string[]\n /** Proxy directory override (default: node_modules/.react-native-gtkx). */\n proxyDir?: string\n}\n\nconst sanitize = (name: string): string => name.replace(/[@/:]/g, \"_\") + \".js\"\n\nconst hostModuleProxy = (name: string): string =>\n // The run-linux host guarantees __hostModules before executing the bundle.\n `module.exports = global.__hostModules[${JSON.stringify(name)}]\\n`\n\nconst builtinProxy = (name: string): string =>\n `module.exports = global.__hostRequire(${JSON.stringify(name)})\\n`\n\n// Every proxy is generated eagerly when the config loads: Metro crawls the\n// file map before transforming, and files that appear mid-build lose the\n// race (\"Failed to get the SHA-1\"). The builtin list is finite, so the\n// whole proxy set can exist up front.\nconst generateProxies = (dir: string, externals: Set<string>): void => {\n mkdirSync(dir, { recursive: true })\n for (const name of externals) {\n writeFileSync(join(dir, sanitize(name)), hostModuleProxy(name))\n }\n for (const bare of builtinModules) {\n writeFileSync(join(dir, sanitize(bare)), builtinProxy(bare))\n writeFileSync(\n join(dir, sanitize(`node:${bare}`)),\n builtinProxy(`node:${bare}`),\n )\n }\n}\n\nexport type LinuxPlatformConfig<T extends MetroLikeConfig> = T & {\n resolver: {\n platforms: string[]\n resolveRequest: MetroResolver\n }\n serializer: {\n getModulesRunBeforeMainModule: (entryFilePath: string) => string[]\n }\n}\n\n/**\n * Wraps a Metro config (RN's getDefaultConfig output) with everything the\n * linux platform needs. Composes with an existing custom resolveRequest —\n * non-linux platforms fall through to it untouched.\n */\nexport const withLinuxPlatform = <T extends MetroLikeConfig>(\n config: T,\n options: LinuxPlatformOptions = {},\n): LinuxPlatformConfig<T> => {\n const externals = new Set([\n ...HOST_MODULE_EXTERNALS,\n ...(options.externals ?? []),\n ])\n const proxyDir =\n options.proxyDir ??\n join(\n config.projectRoot ?? process.cwd(),\n \"node_modules\",\n \".react-native-gtkx\",\n \"metro-externals\",\n )\n generateProxies(proxyDir, externals)\n const previousResolve = config.resolver?.resolveRequest ?? null\n\n const fallback: MetroResolver = (context, moduleName, platform) =>\n previousResolve\n ? previousResolve(context, moduleName, platform)\n : context.resolveRequest(context, moduleName, platform)\n\n const resolveRequest: MetroResolver = (context, moduleName, platform) => {\n if (platform !== LINUX_PLATFORM) {\n return fallback(context, moduleName, platform)\n }\n if (externals.has(moduleName) || isBuiltin(moduleName)) {\n return {\n type: \"sourceFile\",\n filePath: join(proxyDir, sanitize(moduleName)),\n }\n }\n if (\n moduleName === \"react-native\" ||\n moduleName.startsWith(\"react-native/\")\n ) {\n return fallback(\n context,\n moduleName.replace(/^react-native/, \"react-native-gtkx\"),\n platform,\n )\n }\n return fallback(context, moduleName, platform)\n }\n\n // The cast: T may carry narrower resolver/serializer types than the ones\n // rebuilt here — the runtime shape is a strict superset of both.\n return {\n ...config,\n resolver: {\n ...config.resolver,\n platforms: [\n ...new Set([...(config.resolver?.platforms ?? []), LINUX_PLATFORM]),\n ],\n resolveRequest,\n },\n serializer: {\n ...config.serializer,\n // RN prepends InitializeCore (Hermes Promise, nativeLoggingHook\n // console...). Our runtime environment IS Node — nothing to\n // initialize inside the bundle.\n getModulesRunBeforeMainModule: () => [],\n },\n } as LinuxPlatformConfig<T>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metro/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Metro preset for the linux out-of-tree platform: wrap the app's Metro\n// config with `withLinuxPlatform` and the standard RN toolchain bundles for\n// `--platform linux`.\n//\n// What it does on top of RN defaults (validated by spike/rn-platform):\n//\n// 1. Adds \"linux\" to resolver.platforms (`.linux.tsx` extensions and\n// Platform.OS come along with it).\n// 2. Redirects `react-native` (and subpaths) to `react-native-gtkx` — the\n// out-of-tree npmPackageName declaration alone does not alias imports\n// for `bundle`, the resolver has to.\n// 3. EXTERNALIZES host-side singletons. Unlike react-native-windows, whose\n// native side lives outside the JS bundle by construction, our \"native\"\n// is Node modules with NAPI bindings (@gtkx/*) plus yoga-layout's WASM —\n// Metro cannot bundle those. react (and its jsx runtimes) must also stay\n// host-side: the reconciler inside @gtkx/react and the app have to share\n// one React instance. Every external resolves to a generated proxy that\n// reads the real module from global.__hostModules — the run-linux host\n// injects them before executing the bundle.\n// 4. Proxies Node builtins through the host's require: apps on this\n// platform may use the whole Node API, it is a platform feature.\n// 5. Drops InitializeCore (RN's mobile environment polyfills): the runtime\n// environment IS Node, the host provides everything.\nimport { mkdirSync, writeFileSync } from \"node:fs\"\nimport { builtinModules, isBuiltin } from \"node:module\"\nimport { join } from \"node:path\"\n\n/** Modules the run-linux host provides to the bundle at runtime. */\nexport const HOST_MODULE_EXTERNALS = [\n \"@gtkx/css\",\n \"@gtkx/gi/adw\",\n \"@gtkx/gi/gdk\",\n \"@gtkx/gi/gio\",\n \"@gtkx/gi/glib\",\n \"@gtkx/gi/gobject\",\n \"@gtkx/gi/graphene\",\n \"@gtkx/gi/gsk\",\n \"@gtkx/gi/gtk\",\n \"@gtkx/gi/pango\",\n \"@gtkx/jsx/adw\",\n \"@gtkx/jsx/gio\",\n \"@gtkx/jsx/gtk\",\n \"@gtkx/react\",\n \"@gtkx/react/internal\",\n \"@gtkx/runtime\",\n \"react\",\n \"react/jsx-runtime\",\n \"react/jsx-dev-runtime\",\n \"yoga-layout\",\n]\n\nexport const LINUX_PLATFORM = \"linux\"\n\n// Structural slices of Metro's config/resolution types: Metro is the app's\n// dependency, not ours — depending on its types here would pin versions.\nexport type MetroResolutionContext = {\n resolveRequest: MetroResolver\n}\nexport type MetroResolution = { type: string; filePath?: string }\nexport type MetroResolver = (\n context: MetroResolutionContext,\n moduleName: string,\n platform: string | null,\n) => MetroResolution\n\nexport type MetroLikeConfig = {\n projectRoot?: string\n resolver?: {\n platforms?: readonly string[]\n resolveRequest?: MetroResolver | null\n }\n serializer?: {\n getModulesRunBeforeMainModule?: (entryFilePath: string) => string[]\n }\n}\n\nexport type LinuxPlatformOptions = {\n /** Extra host-provided modules to keep out of the bundle. */\n externals?: readonly string[]\n /** Proxy directory override (default: node_modules/.react-native-gtkx). */\n proxyDir?: string\n}\n\nconst sanitize = (name: string): string => name.replace(/[@/:]/g, \"_\") + \".js\"\n\nconst hostModuleProxy = (name: string): string =>\n // The run-linux host guarantees __hostModules before executing the bundle.\n `module.exports = global.__hostModules[${JSON.stringify(name)}]\\n`\n\nconst builtinProxy = (name: string): string =>\n `module.exports = global.__hostRequire(${JSON.stringify(name)})\\n`\n\n// Every proxy is generated eagerly when the config loads: Metro crawls the\n// file map before transforming, and files that appear mid-build lose the\n// race (\"Failed to get the SHA-1\"). The builtin list is finite, so the\n// whole proxy set can exist up front.\nconst generateProxies = (dir: string, externals: Set<string>): void => {\n mkdirSync(dir, { recursive: true })\n for (const name of externals) {\n writeFileSync(join(dir, sanitize(name)), hostModuleProxy(name))\n }\n for (const bare of builtinModules) {\n writeFileSync(join(dir, sanitize(bare)), builtinProxy(bare))\n writeFileSync(\n join(dir, sanitize(`node:${bare}`)),\n builtinProxy(`node:${bare}`),\n )\n }\n}\n\nexport type LinuxPlatformConfig<T extends MetroLikeConfig> = T & {\n resolver: {\n platforms: string[]\n resolveRequest: MetroResolver\n }\n serializer: {\n getModulesRunBeforeMainModule: (entryFilePath: string) => string[]\n }\n}\n\n/**\n * Wraps a Metro config (RN's getDefaultConfig output) with everything the\n * linux platform needs. Composes with an existing custom resolveRequest —\n * non-linux platforms fall through to it untouched.\n */\nexport const withLinuxPlatform = <T extends MetroLikeConfig>(\n config: T,\n options: LinuxPlatformOptions = {},\n): LinuxPlatformConfig<T> => {\n const externals = new Set([\n ...HOST_MODULE_EXTERNALS,\n ...(options.externals ?? []),\n ])\n const proxyDir =\n options.proxyDir ??\n join(\n config.projectRoot ?? process.cwd(),\n \"node_modules\",\n \".react-native-gtkx\",\n \"metro-externals\",\n )\n generateProxies(proxyDir, externals)\n const previousResolve = config.resolver?.resolveRequest ?? null\n\n const fallback: MetroResolver = (context, moduleName, platform) =>\n previousResolve\n ? previousResolve(context, moduleName, platform)\n : context.resolveRequest(context, moduleName, platform)\n\n const resolveRequest: MetroResolver = (context, moduleName, platform) => {\n if (platform !== LINUX_PLATFORM) {\n return fallback(context, moduleName, platform)\n }\n if (externals.has(moduleName) || isBuiltin(moduleName)) {\n return {\n type: \"sourceFile\",\n filePath: join(proxyDir, sanitize(moduleName)),\n }\n }\n if (\n moduleName === \"react-native\" ||\n moduleName.startsWith(\"react-native/\")\n ) {\n return fallback(\n context,\n moduleName.replace(/^react-native/, \"react-native-gtkx\"),\n platform,\n )\n }\n // Same alias, same guard shape, for the SVG compat subpath (see\n // src/svg-compat/index.ts and the vite preset's rewriteReactNativeImport\n // — kept in sync deliberately rather than sharing code, Metro and vite\n // resolvers have never shared an implementation in this package).\n if (\n moduleName === \"react-native-svg\" ||\n moduleName.startsWith(\"react-native-svg/\")\n ) {\n return fallback(\n context,\n moduleName.replace(/^react-native-svg/, \"react-native-gtkx/svg\"),\n platform,\n )\n }\n return fallback(context, moduleName, platform)\n }\n\n // The cast: T may carry narrower resolver/serializer types than the ones\n // rebuilt here — the runtime shape is a strict superset of both.\n return {\n ...config,\n resolver: {\n ...config.resolver,\n platforms: [\n ...new Set([...(config.resolver?.platforms ?? []), LINUX_PLATFORM]),\n ],\n resolveRequest,\n },\n serializer: {\n ...config.serializer,\n // RN prepends InitializeCore (Hermes Promise, nativeLoggingHook\n // console...). Our runtime environment IS Node — nothing to\n // initialize inside the bundle.\n getModulesRunBeforeMainModule: () => [],\n },\n } as LinuxPlatformConfig<T>\n}\n"]}
|
|
@@ -1,30 +1,64 @@
|
|
|
1
|
-
import { type NavigationProp, type ParamListBase, type RouteProp, type StackNavigationState } from "@react-navigation/native";
|
|
1
|
+
import { type NavigationProp, type NavigatorTypeBagBase, type NavigatorTypeBagFor, type ParamListBase, type RouteProp, type StackNavigationState, type TypedNavigator } from "@react-navigation/native";
|
|
2
2
|
import { type ComponentType, type ReactNode } from "react";
|
|
3
3
|
import type { HeaderButton } from "./sidebar";
|
|
4
4
|
export type StackNavigationOptions = {
|
|
5
|
-
/**
|
|
5
|
+
/** AdwHeaderBar title; defaults to the route name. */
|
|
6
6
|
title?: string;
|
|
7
|
-
/** Render the
|
|
7
|
+
/** Render the Adwaitan AdwHeaderBar for this screen (default true). */
|
|
8
8
|
headerShown?: boolean;
|
|
9
|
-
/** Buttons packed at the end of this screen's
|
|
9
|
+
/** Buttons packed at the end of this screen's AdwHeaderBar (see
|
|
10
10
|
* HeaderButton); screens usually set them via navigation.setOptions. */
|
|
11
11
|
headerButtons?: HeaderButton[];
|
|
12
|
-
/** RN content packed at the start of the
|
|
12
|
+
/** RN content packed at the start of the AdwHeaderBar (an intrinsic-size
|
|
13
13
|
* layout root: the content's Yoga size IS the slot size). */
|
|
14
14
|
headerLeft?: () => ReactNode;
|
|
15
|
-
/** RN content packed at the end of the
|
|
15
|
+
/** RN content packed at the end of the AdwHeaderBar, before headerButtons. */
|
|
16
16
|
headerRight?: () => ReactNode;
|
|
17
17
|
/** false disables the native back button, Escape and the back gesture
|
|
18
18
|
* for this screen (the page's Adwaita can-pop). Programmatic goBack
|
|
19
19
|
* still works. Also the mechanism behind usePreventRemove. */
|
|
20
20
|
gestureEnabled?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* `"none"` turns transitions off; any other value (including the
|
|
23
|
+
* `@react-navigation/native-stack` style names like `"slide_from_bottom"`
|
|
24
|
+
* or `"fade"`) turns them on. GTK has exactly one transition style, so a
|
|
25
|
+
* specific requested type cannot be honored — only whether to animate at
|
|
26
|
+
* all can be. Requesting a specific (non-`"default"`) type still animates,
|
|
27
|
+
* with the standard Adwaita transition, and warns once in development.
|
|
28
|
+
* Read from whichever screen is currently on top of the visible stack, so
|
|
29
|
+
* setting it uniformly via `screenOptions` is the reliable way to use it —
|
|
30
|
+
* see docs/api.md.
|
|
31
|
+
*/
|
|
32
|
+
animation?: string;
|
|
33
|
+
};
|
|
34
|
+
export type StackNavigationEventMap = {
|
|
35
|
+
/** Fires when a push/pop/replace transition starts, once per involved
|
|
36
|
+
* route (not once per gesture or user tap). */
|
|
37
|
+
transitionStart: {
|
|
38
|
+
data: {
|
|
39
|
+
closing: boolean;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
/** Fires when the transition settles, driven by the page's own real
|
|
43
|
+
* `shown`/`hidden` AdwNavigationPage signal (see docs/api.md and the
|
|
44
|
+
* primitive's beginTransition) — not a timer, except as a fallback for
|
|
45
|
+
* the rare cases where neither signal arrives. Native pops (back
|
|
46
|
+
* button, Escape, back gesture) do not fire this at all today — see
|
|
47
|
+
* docs/api.md. */
|
|
48
|
+
transitionEnd: {
|
|
49
|
+
data: {
|
|
50
|
+
closing: boolean;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
21
53
|
};
|
|
22
54
|
type StackNavigatorProps = {
|
|
23
55
|
initialRouteName?: string;
|
|
24
56
|
screenOptions?: StackNavigationOptions;
|
|
25
57
|
children: ReactNode;
|
|
26
58
|
};
|
|
27
|
-
|
|
59
|
+
declare const StackNavigator: ({ initialRouteName, screenOptions, children, }: StackNavigatorProps) => React.JSX.Element;
|
|
60
|
+
export { createSidebarNavigator, type HeaderButton, type SidebarNavigationEventMap, type SidebarNavigationHelpers, type SidebarNavigationOptions, type SidebarScreenConfig, type SidebarScreenProps, type TypedSidebarNavigator, } from "./sidebar";
|
|
61
|
+
export type StackNavigationHelpers<ParamList extends ParamListBase = ParamListBase, RouteName extends keyof ParamList = keyof ParamList> = NavigationProp<ParamList, RouteName, StackNavigationState<ParamList>, StackNavigationOptions, StackNavigationEventMap>;
|
|
28
62
|
export type StackScreenProps<ParamList extends ParamListBase = ParamListBase, RouteName extends keyof ParamList = keyof ParamList> = {
|
|
29
63
|
route: RouteProp<ParamList, RouteName>;
|
|
30
64
|
navigation: StackNavigationHelpers<ParamList, RouteName>;
|
|
@@ -35,10 +69,13 @@ export type StackScreenConfig<ParamList extends ParamListBase, RouteName extends
|
|
|
35
69
|
options?: StackNavigationOptions | ((props: StackScreenProps<ParamList, RouteName>) => StackNavigationOptions);
|
|
36
70
|
initialParams?: Partial<ParamList[RouteName]>;
|
|
37
71
|
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
72
|
+
interface StackTypeBag extends NavigatorTypeBagBase {
|
|
73
|
+
ParamList: ParamListBase;
|
|
74
|
+
State: StackNavigationState<ParamListBase>;
|
|
75
|
+
ScreenOptions: StackNavigationOptions;
|
|
76
|
+
EventMap: StackNavigationEventMap;
|
|
77
|
+
ActionHelpers: Record<string, () => void>;
|
|
78
|
+
Navigator: typeof StackNavigator;
|
|
79
|
+
}
|
|
80
|
+
export type TypedStackNavigator<ParamList extends ParamListBase> = TypedNavigator<NavigatorTypeBagFor<StackTypeBag, ParamList>, undefined>;
|
|
42
81
|
export declare const createStackNavigator: <ParamList extends ParamListBase = ParamListBase>() => TypedStackNavigator<ParamList>;
|
|
43
|
-
export { createSidebarNavigator, type HeaderButton, type SidebarNavigationOptions, type SidebarScreenConfig, type SidebarScreenProps, type TypedSidebarNavigator, } from "./sidebar";
|
|
44
|
-
export { CommonActions, NavigationContainer, StackActions, useFocusEffect, useIsFocused, useNavigation, useNavigationContainerRef, usePreventRemove, useRoute, } from "@react-navigation/native";
|
package/dist/navigation/index.js
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
// react-native-gtkx/navigation — a react-navigation stack navigator backed
|
|
3
|
-
// by Adw.NavigationView
|
|
4
|
-
// on iOS (UINavigationController): react-navigation state is the source of
|
|
5
|
-
// truth, the native view is imperatively synced to it, and NATIVE pops (the
|
|
6
|
-
// Adwaita back button, Escape, the back gesture) are reported back through
|
|
7
|
-
// the "popped" signal.
|
|
3
|
+
// by the Adw.NavigationView primitive from react-native-gtkx/adwaita.
|
|
8
4
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// -
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
5
|
+
// This file is an ADAPTER and nothing else. Every widget concern — diffing
|
|
6
|
+
// the tag stack into pushes and pops, holding a popped page alive until its
|
|
7
|
+
// exit animation ends, bracketing transitions — lives in the primitive. What
|
|
8
|
+
// stays here is exactly the react-navigation half:
|
|
9
|
+
//
|
|
10
|
+
// - state → the ordered tags handed to NavigationStack (route keys);
|
|
11
|
+
// - a native pop (back button, Escape, back gesture) → StackActions.pop,
|
|
12
|
+
// but only when the tag is still in state, otherwise the pop was one WE
|
|
13
|
+
// caused and echoing it would double-pop;
|
|
14
|
+
// - descriptors → page titles, header content and canPop;
|
|
15
|
+
// - unknown-option warnings.
|
|
16
|
+
//
|
|
17
|
+
// The same split as @react-navigation/native-stack over react-native-screens.
|
|
18
|
+
// If you do not want a router, use the primitive directly.
|
|
18
19
|
import { createNavigatorFactory, StackActions, StackRouter, useNavigationBuilder, usePreventRemoveContext, } from "@react-navigation/native";
|
|
19
|
-
import {
|
|
20
|
-
import { InteractionManager } from "../apis/interaction-manager";
|
|
20
|
+
import { useEffect, useRef } from "react";
|
|
21
21
|
import { getActiveChrome } from "../components/app-registry";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
22
|
+
import { AdwHeaderBar, AdwToolbarView } from "../adw";
|
|
23
|
+
import { HeaderSlotContent, NavigationStack, NavigationStackPage, SlotContent, } from "../common";
|
|
24
|
+
import { GtkButton } from "../gtkx/bridge/index";
|
|
24
25
|
import { warnIgnoredOptions } from "./option-warnings";
|
|
25
26
|
const STACK_OPTION_KEYS = new Set([
|
|
26
27
|
"title",
|
|
@@ -29,6 +30,7 @@ const STACK_OPTION_KEYS = new Set([
|
|
|
29
30
|
"headerLeft",
|
|
30
31
|
"headerRight",
|
|
31
32
|
"gestureEnabled",
|
|
33
|
+
"animation",
|
|
32
34
|
]);
|
|
33
35
|
const StackNavigator = ({ initialRouteName, screenOptions, children, }) => {
|
|
34
36
|
const { state, descriptors, navigation, NavigationContent } = useNavigationBuilder(StackRouter, {
|
|
@@ -36,12 +38,47 @@ const StackNavigator = ({ initialRouteName, screenOptions, children, }) => {
|
|
|
36
38
|
screenOptions,
|
|
37
39
|
children,
|
|
38
40
|
});
|
|
39
|
-
|
|
41
|
+
// React Navigation 8: `state.routes` is no longer just the visible stack —
|
|
42
|
+
// it is active routes followed by retained routes (closing, kept mounted
|
|
43
|
+
// for `inactiveBehavior`) and preloaded routes (`navigation.preload()`,
|
|
44
|
+
// not yet navigated to), all concatenated, with the focused/visible tail
|
|
45
|
+
// ending at `state.index` (see StackRouter's `getStateWithRoutes`: `routes:
|
|
46
|
+
// activeRoutes.concat(retainedRoutes, preloadedRoutes)`, `index:
|
|
47
|
+
// activeRoutes.length - 1`). Handing the whole array to NavigationStack
|
|
48
|
+
// would push a preloaded screen onto the widget as if it were a real page
|
|
49
|
+
// the user navigated to. Only the active slice is the visible stack.
|
|
50
|
+
const visibleRoutes = state.routes.slice(0, state.index + 1);
|
|
51
|
+
const visibleKeys = visibleRoutes.map((route) => route.key);
|
|
52
|
+
// GTK has exactly one transition style and one animate-transitions switch
|
|
53
|
+
// for the whole view — there is no per-route knob to hand it. The screen
|
|
54
|
+
// actually being navigated TO is the natural read of "the currently
|
|
55
|
+
// relevant animation option": for a push, that is the new top of stack;
|
|
56
|
+
// for a pop, the screen the pop reveals. An app that sets `animation`
|
|
57
|
+
// uniformly through `screenOptions` (the common case for "turn animation
|
|
58
|
+
// off entirely") gets the same value everywhere, so this only matters
|
|
59
|
+
// when different screens genuinely disagree.
|
|
60
|
+
const activeRouteKey = visibleKeys[visibleKeys.length - 1];
|
|
61
|
+
const activeDescriptor = activeRouteKey
|
|
62
|
+
? descriptors[activeRouteKey]
|
|
63
|
+
: undefined;
|
|
64
|
+
const animateTransitions = activeDescriptor?.options.animation !== "none";
|
|
40
65
|
useEffect(() => {
|
|
41
66
|
for (const route of state.routes) {
|
|
42
67
|
const descriptor = descriptors[route.key];
|
|
43
68
|
if (descriptor) {
|
|
44
69
|
warnIgnoredOptions("createStackNavigator", descriptor.options, STACK_OPTION_KEYS);
|
|
70
|
+
const { animation } = descriptor.options;
|
|
71
|
+
// "animation" itself is in STACK_OPTION_KEYS above (it IS honored,
|
|
72
|
+
// collapsed to a boolean), so the call above never flags it. A
|
|
73
|
+
// specific requested type — anything but "none" (handled) or
|
|
74
|
+
// "default" (not a specific request) — is a separate, narrower
|
|
75
|
+
// complaint, forced through the same verdict lookup and the same
|
|
76
|
+
// once-per-navigator-per-key dedupe with an empty supported set.
|
|
77
|
+
if (animation !== undefined &&
|
|
78
|
+
animation !== "none" &&
|
|
79
|
+
animation !== "default") {
|
|
80
|
+
warnIgnoredOptions("createStackNavigator", { animation }, new Set());
|
|
81
|
+
}
|
|
45
82
|
}
|
|
46
83
|
}
|
|
47
84
|
}, [state, descriptors]);
|
|
@@ -51,127 +88,129 @@ const StackNavigator = ({ initialRouteName, screenOptions, children, }) => {
|
|
|
51
88
|
console.warn('[react-native-gtkx/navigation] the app runs with the default window chrome — pages bring their own HeaderBars, so you will see a doubled titlebar. Pass chrome: "content" to AppRegistry.runApplication.');
|
|
52
89
|
}
|
|
53
90
|
}, []);
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// therefore render from renderedKeys — live routes plus closing pages —
|
|
61
|
-
// and a closing page leaves only on its "hidden" signal (the end of the
|
|
62
|
-
// transition). Its content renders from a snapshot cached while live.
|
|
63
|
-
const [renderedKeys, setRenderedKeys] = useState(() => state.routes.map((route) => route.key));
|
|
64
|
-
const liveKeys = state.routes.map((route) => route.key);
|
|
65
|
-
const missingKeys = liveKeys.filter((key) => !renderedKeys.includes(key));
|
|
66
|
-
if (missingKeys.length > 0) {
|
|
67
|
-
// The sanctioned derive-state-during-render pattern: a new route must be
|
|
68
|
-
// in renderedKeys within the same commit its page is pushed.
|
|
69
|
-
setRenderedKeys([...renderedKeys, ...missingKeys]);
|
|
70
|
-
}
|
|
71
|
-
// A state-held stable Map (not a ref): the render path reads it for
|
|
72
|
-
// closing pages, and the react-hooks/refs rule rightly bans render-time
|
|
73
|
-
// ref reads.
|
|
74
|
-
const [snapshots] = useState(() => new Map());
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
for (const route of state.routes) {
|
|
77
|
-
const descriptor = descriptors[route.key];
|
|
78
|
-
if (descriptor) {
|
|
79
|
-
snapshots.set(route.key, {
|
|
80
|
-
name: route.name,
|
|
81
|
-
options: descriptor.options,
|
|
82
|
-
element: _jsx(NestedRoot, { children: descriptor.render() }),
|
|
83
|
-
});
|
|
84
|
-
}
|
|
91
|
+
// `navigation` is identity-stable across renders (react-navigation builder
|
|
92
|
+
// contract) and getState() always reads the live state — no ref needed.
|
|
93
|
+
const handlePopped = (tag) => {
|
|
94
|
+
if (navigation.getState().routes.some((route) => route.key === tag)) {
|
|
95
|
+
// Still in state, so the WIDGET popped on its own: follow in state.
|
|
96
|
+
navigation.dispatch(StackActions.pop());
|
|
85
97
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
// Otherwise state dropped the route first and the primitive is merely
|
|
99
|
+
// reporting the animation we asked for. Nothing to do.
|
|
100
|
+
};
|
|
101
|
+
// transitionStart/transitionEnd: translates NavigationStack's primitive
|
|
102
|
+
// callbacks into react-navigation's own per-route events, matching
|
|
103
|
+
// @react-navigation/stack and @react-navigation/native-stack's v8
|
|
104
|
+
// behavior byte for byte (verified against their source, not docs — see
|
|
105
|
+
// 007.md): a route that just became visible fires `closing: false`, a
|
|
106
|
+
// route that just left the visible stack fires `closing: true`, and a
|
|
107
|
+
// route whose visibility did not change (e.g. covered by a push) gets
|
|
108
|
+
// neither event.
|
|
109
|
+
//
|
|
110
|
+
// The start and end sides deliberately use TWO DIFFERENT primitive
|
|
111
|
+
// signals, not the same onTransitionStart/onTransitionEnd pair for both:
|
|
112
|
+
//
|
|
113
|
+
// - transitionStart (both directions) rides onTransitionStart, a
|
|
114
|
+
// view-level "a transition just began" signal with no per-route
|
|
115
|
+
// identity — the adapter supplies that identity itself by diffing
|
|
116
|
+
// visibleKeys against the previous render's visible keys.
|
|
117
|
+
// - transitionEnd for an OPENING route also rides the view-level
|
|
118
|
+
// onTransitionEnd, itself driven by the pushed page's own real "shown"
|
|
119
|
+
// signal (transitionDuration only as a fallback — see docs/api.md and
|
|
120
|
+
// the primitive's beginTransition): the pushed screen stays mounted
|
|
121
|
+
// indefinitely once it is the active page, so nothing about that is
|
|
122
|
+
// unsafe here either way.
|
|
123
|
+
// - transitionEnd for a CLOSING route rides onPageClosed instead, fired
|
|
124
|
+
// PER TAG when that page's exit actually finishes (a real GTK
|
|
125
|
+
// "hidden" signal when available, the primitive's own timer as
|
|
126
|
+
// fallback). This was not a style choice: routing the closing side
|
|
127
|
+
// through the generic view-level timer was tried first and is wrong
|
|
128
|
+
// whenever the real close finishes before the fixed transitionDuration
|
|
129
|
+
// default (guaranteed in headless test environments with animations
|
|
130
|
+
// disabled, and possible on a real desktop too) — the closing screen's
|
|
131
|
+
// React component has already unmounted (and unsubscribed its
|
|
132
|
+
// listeners) by the time the generic, one-size-fits-all timer gets
|
|
133
|
+
// around to firing, so the event never reaches anyone. onPageClosed
|
|
134
|
+
// fires synchronously before React commits that unmount, so the
|
|
135
|
+
// listener is still there to receive it.
|
|
136
|
+
//
|
|
137
|
+
// previousVisibleKeysRef is compared by CONTENT, not a call-count flag:
|
|
138
|
+
// NavigationStack's sync effect can call beginTransition() (hence
|
|
139
|
+
// onTransitionStart) more than once for one state update — e.g. popping
|
|
140
|
+
// back past two routes and pushing two new ones in the same dispatch
|
|
141
|
+
// calls it three times — and every one of those calls closes over the
|
|
142
|
+
// SAME visibleKeys for this render. Diffing against the ref and only
|
|
143
|
+
// then updating it makes every call after the first a no-op (the ref
|
|
144
|
+
// already equals visibleKeys), without a manual "already handling a
|
|
145
|
+
// transition" flag that would also incorrectly swallow a second,
|
|
146
|
+
// genuinely separate transition starting before the first one settles.
|
|
147
|
+
const previousVisibleKeysRef = useRef(visibleKeys);
|
|
148
|
+
const pendingOpeningEndRef = useRef([]);
|
|
149
|
+
// Tags this adapter itself put in flight via transitionStart(closing:
|
|
150
|
+
// true) — NOT every tag onPageClosed ever reports. A native pop (back
|
|
151
|
+
// button, Escape, back gesture) also eventually drops its tag through
|
|
152
|
+
// the exact same primitive mechanism, but never called beginTransition()
|
|
153
|
+
// (see the primitive: a native pop's own handlePopped reconciles
|
|
154
|
+
// syncedRef directly, so the sync effect finds nothing left to push or
|
|
155
|
+
// pop once react-navigation's state catches up) — so it never got a
|
|
156
|
+
// transitionStart either. Without this guard, handlePageClosed would
|
|
157
|
+
// emit a transitionEnd with no matching transitionStart for every native
|
|
158
|
+
// pop, which is worse than emitting neither: a listener would see an
|
|
159
|
+
// end event out of nowhere. Documented as Known limitation #2 in 007.md
|
|
160
|
+
// — native pops fire neither event today.
|
|
161
|
+
const pendingClosingRef = useRef(new Set());
|
|
162
|
+
const emitTransitionEvent = (type, keys, closing) => {
|
|
163
|
+
for (const key of keys) {
|
|
164
|
+
navigation.emit({ type, data: { closing }, target: key });
|
|
92
165
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const scheduleRetainedRemoval = useCallback((key) => {
|
|
101
|
-
setTimeout(() => handleHidden(key), 400);
|
|
102
|
-
}, [handleHidden]);
|
|
103
|
-
// Bracket every view transition with an InteractionManager handle so
|
|
104
|
-
// runAfterInteractions-scheduled work (a screen's own data load / heavy
|
|
105
|
-
// render) waits for the slide to finish instead of stealing its frames.
|
|
106
|
-
// The handle is opened when the sync effect mutates the view and cleared
|
|
107
|
-
// one transition-length later; overlapping transitions reference-count.
|
|
108
|
-
const beginTransition = useCallback(() => {
|
|
109
|
-
const handle = InteractionManager.createInteractionHandle();
|
|
110
|
-
setTimeout(() => InteractionManager.clearInteractionHandle(handle), 400);
|
|
111
|
-
}, []);
|
|
112
|
-
useEffect(() => {
|
|
113
|
-
const view = viewRef.current;
|
|
114
|
-
if (!view) {
|
|
166
|
+
};
|
|
167
|
+
const handleTransitionStart = () => {
|
|
168
|
+
const previous = previousVisibleKeysRef.current;
|
|
169
|
+
if (previous.length === visibleKeys.length &&
|
|
170
|
+
previous.every((key, index) => key === visibleKeys[index])) {
|
|
171
|
+
// A duplicate beginTransition() call for the same commit (see
|
|
172
|
+
// above) — already diffed by an earlier call this render.
|
|
115
173
|
return;
|
|
116
174
|
}
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
175
|
+
const opening = visibleKeys.filter((key) => !previous.includes(key));
|
|
176
|
+
const closing = previous.filter((key) => !visibleKeys.includes(key));
|
|
177
|
+
previousVisibleKeysRef.current = visibleKeys;
|
|
178
|
+
pendingOpeningEndRef.current.push(...opening);
|
|
179
|
+
for (const key of closing) {
|
|
180
|
+
pendingClosingRef.current.add(key);
|
|
121
181
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
for (const key of leaving) {
|
|
135
|
-
scheduleRetainedRemoval(key);
|
|
136
|
-
}
|
|
182
|
+
emitTransitionEvent("transitionStart", opening, false);
|
|
183
|
+
emitTransitionEvent("transitionStart", closing, true);
|
|
184
|
+
};
|
|
185
|
+
// Drains whatever opening keys are pending rather than trusting call
|
|
186
|
+
// count, for the same reason handleTransitionStart diffs by content: a
|
|
187
|
+
// compound update's several onTransitionEnd calls (one per
|
|
188
|
+
// beginTransition() above) all land at essentially the same moment, so
|
|
189
|
+
// the first one emits everything queued and the rest find nothing left
|
|
190
|
+
// to drain. Closing keys are NOT handled here — see handlePageClosed.
|
|
191
|
+
const handleTransitionEnd = () => {
|
|
192
|
+
const opening = pendingOpeningEndRef.current;
|
|
193
|
+
if (opening.length === 0) {
|
|
137
194
|
return;
|
|
138
195
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
for (const key of leaving) {
|
|
148
|
-
scheduleRetainedRemoval(key);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
for (let index = syncedRef.current.length; index < target.length; index += 1) {
|
|
152
|
-
const key = target[index];
|
|
153
|
-
syncedRef.current.push(key);
|
|
154
|
-
beginTransition();
|
|
155
|
-
view.pushByTag(key);
|
|
156
|
-
}
|
|
157
|
-
}, [state, scheduleRetainedRemoval, beginTransition]);
|
|
158
|
-
// `navigation` is identity-stable across renders (react-navigation
|
|
159
|
-
// builder contract) and getState() always reads the live state — the
|
|
160
|
-
// closure needs no ref indirection.
|
|
161
|
-
const handlePopped = (page) => {
|
|
162
|
-
const tag = page?.getTag();
|
|
163
|
-
if (!tag) {
|
|
196
|
+
pendingOpeningEndRef.current = [];
|
|
197
|
+
emitTransitionEvent("transitionEnd", opening, false);
|
|
198
|
+
};
|
|
199
|
+
const handlePageClosed = (tag) => {
|
|
200
|
+
if (!pendingClosingRef.current.has(tag)) {
|
|
201
|
+
// Not a tag this adapter put in flight (a native pop, or a stray
|
|
202
|
+
// call) — no transitionStart was ever emitted for it, so no
|
|
203
|
+
// transitionEnd either.
|
|
164
204
|
return;
|
|
165
205
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
scheduleRetainedRemoval(tag);
|
|
206
|
+
pendingClosingRef.current.delete(tag);
|
|
207
|
+
navigation.emit({
|
|
208
|
+
type: "transitionEnd",
|
|
209
|
+
data: { closing: true },
|
|
210
|
+
target: tag,
|
|
211
|
+
});
|
|
173
212
|
};
|
|
174
|
-
return (_jsx(NavigationContent, { children: _jsx(StackView, {
|
|
213
|
+
return (_jsx(NavigationContent, { children: _jsx(StackView, { routeKeys: visibleKeys, descriptors: descriptors, animateTransitions: animateTransitions, onPopped: handlePopped, onTransitionStart: handleTransitionStart, onTransitionEnd: handleTransitionEnd, onPageClosed: handlePageClosed }) }));
|
|
175
214
|
};
|
|
176
215
|
// The page list lives inside NavigationContent so it can read the
|
|
177
216
|
// prevent-remove context (which useNavigationBuilder only provides to
|
|
@@ -181,36 +220,32 @@ const StackNavigator = ({ initialRouteName, screenOptions, children, }) => {
|
|
|
181
220
|
// programmatic goBack still pops (once the app lifts the prevention, e.g.
|
|
182
221
|
// after its own confirmation dialog). This is why a native pop can never
|
|
183
222
|
// race react-navigation state for these routes.
|
|
184
|
-
const StackView = ({
|
|
223
|
+
const StackView = ({ routeKeys, descriptors, animateTransitions, onPopped, onTransitionStart, onTransitionEnd, onPageClosed, }) => {
|
|
185
224
|
const { preventedRoutes } = usePreventRemoveContext();
|
|
186
|
-
return (_jsx(
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
const options = descriptor?.options ?? snapshot?.options ?? {};
|
|
225
|
+
return (_jsx(NavigationStack, { stack: routeKeys, animateTransitions: animateTransitions, onPopped: onPopped, onTransitionStart: onTransitionStart, onTransitionEnd: onTransitionEnd, onPageClosed: onPageClosed, children: routeKeys.map((key) => {
|
|
226
|
+
const descriptor = descriptors[key];
|
|
227
|
+
if (!descriptor) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
const options = descriptor.options;
|
|
193
231
|
const headerShown = options.headerShown ?? true;
|
|
194
232
|
const canPop = options.gestureEnabled !== false &&
|
|
195
233
|
!preventedRoutes[key]?.preventRemove;
|
|
196
|
-
const content =
|
|
197
|
-
return (_jsx(
|
|
198
|
-
// Never the route key — that is an internal identifier, and
|
|
199
|
-
//
|
|
200
|
-
title: options.title ?? descriptor
|
|
234
|
+
const content = _jsx(SlotContent, { children: descriptor.render() });
|
|
235
|
+
return (_jsx(NavigationStackPage, { tag: key,
|
|
236
|
+
// Never the route key — that is an internal identifier, and it
|
|
237
|
+
// would end up in the window title under content chrome.
|
|
238
|
+
title: options.title ?? descriptor.route.name, canPop: canPop, children: headerShown ? (_jsx(AdwToolbarView, { topBar: _jsx(AdwHeaderBar, { start: options.headerLeft ? (_jsx(HeaderSlotContent, { children: options.headerLeft() })) : undefined, end: [
|
|
201
239
|
...(options.headerRight
|
|
202
240
|
? [
|
|
203
|
-
_jsx(
|
|
241
|
+
_jsx(HeaderSlotContent, { children: options.headerRight() }, "header-right"),
|
|
204
242
|
]
|
|
205
243
|
: []),
|
|
206
244
|
...(options.headerButtons?.map((button) => (_jsx(GtkButton, { iconName: button.icon, tooltipText: button.tooltip, onClicked: button.onPress }, button.id))) ?? []),
|
|
207
245
|
] }), children: content })) : (content) }, key));
|
|
208
246
|
}) }));
|
|
209
247
|
};
|
|
248
|
+
export { createSidebarNavigator, } from "./sidebar";
|
|
210
249
|
const stackFactory = createNavigatorFactory(StackNavigator);
|
|
211
250
|
export const createStackNavigator = () => stackFactory();
|
|
212
|
-
export { createSidebarNavigator, } from "./sidebar";
|
|
213
|
-
// The rest of the react-navigation surface apps need, so a linux app can
|
|
214
|
-
// import everything from one place.
|
|
215
|
-
export { CommonActions, NavigationContainer, StackActions, useFocusEffect, useIsFocused, useNavigation, useNavigationContainerRef, usePreventRemove, useRoute, } from "@react-navigation/native";
|
|
216
251
|
//# sourceMappingURL=index.js.map
|