@gtkx/react 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -161,7 +161,7 @@ Explore the [example apps](https://github.com/gtkx-org/gtkx/tree/main/examples):
161
161
 
162
162
  ## Status
163
163
 
164
- GTKX 1.0 is released.
164
+ GTKX is stable and ready for production use.
165
165
 
166
166
  ## Contributing
167
167
 
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/adw/dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAe,MAAM,OAAO,CAAC;AAGtE,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEnG,KAAK,oBAAoB,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAiBvD,QAAA,MAAM,qBAAqB,GAAI,WAAW,WAAW,KAAG,CAAC,CAAC,KAAK,EAAE,oBAAoB,KAAK,SAAS,CAM9F,CAAC;AAEN,gBAAgB;AAChB,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/adw/dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAe,MAAM,OAAO,CAAC;AAGtE,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGnG,KAAK,oBAAoB,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAmBvD,QAAA,MAAM,qBAAqB,GAAI,WAAW,WAAW,KAAG,CAAC,CAAC,KAAK,EAAE,oBAAoB,KAAK,SAAS,CAM9F,CAAC;AAEN,gBAAgB;AAChB,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
@@ -2,8 +2,11 @@ import { useCallback } from "react";
2
2
  import { createPortaledComponent } from "../components/portaled.js";
3
3
  import { useParentWindow } from "../hooks/use-parent-window.js";
4
4
  import { createPresentedComponent } from "../hooks/use-presented-instance.js";
5
+ import { applyWrite } from "../reconciler/signals.js";
5
6
  const closeDialog = (dialog) => {
6
- dialog.forceClose();
7
+ applyWrite(() => {
8
+ dialog.forceClose();
9
+ });
7
10
  };
8
11
  const usePresentDialog = () => {
9
12
  const parent = useParentWindow();
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.js","sourceRoot":"","sources":["../../src/adw/dialog.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoC,WAAW,EAAE,MAAM,OAAO,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAuB,MAAM,oCAAoC,CAAC;AAInG,MAAM,WAAW,GAAG,CAAC,MAAkB,EAAQ,EAAE;IAC7C,MAAM,CAAC,UAAU,EAAE,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,GAAmC,EAAE;IAC1D,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IAEjC,OAAO,WAAW,CACd,CAAC,MAAkB,EAAE,EAAE;QACnB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC,EACD,CAAC,MAAM,CAAC,CACX,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,SAAsB,EAAgD,EAAE,CACnG,uBAAuB,CACnB,wBAAwB,CAAa,SAAS,EAAE;IAC5C,UAAU,EAAE,gBAAgB;IAC5B,OAAO,EAAE,WAAW;CACvB,CAAC,CACL,CAAC;AAEN,gBAAgB;AAChB,OAAO,EAAE,qBAAqB,EAAE,CAAC","sourcesContent":["import type * as Adw from \"@gtkx/gi/adw\";\nimport { type ElementType, type ReactNode, useCallback } from \"react\";\nimport { createPortaledComponent } from \"../components/portaled.js\";\nimport { useParentWindow } from \"../hooks/use-parent-window.js\";\nimport { createPresentedComponent, type PresentedProps } from \"../hooks/use-presented-instance.js\";\n\ntype DialogComponentProps = PresentedProps<Adw.Dialog>;\n\nconst closeDialog = (dialog: Adw.Dialog): void => {\n dialog.forceClose();\n};\n\nconst usePresentDialog = (): ((dialog: Adw.Dialog) => void) => {\n const parent = useParentWindow();\n\n return useCallback(\n (dialog: Adw.Dialog) => {\n dialog.present(parent);\n },\n [parent],\n );\n};\n\nconst createDialogComponent = (Component: ElementType): ((props: DialogComponentProps) => ReactNode) =>\n createPortaledComponent(\n createPresentedComponent<Adw.Dialog>(Component, {\n usePresent: usePresentDialog,\n dismiss: closeDialog,\n }),\n );\n\n/** @internal */\nexport { createDialogComponent };\n"]}
1
+ {"version":3,"file":"dialog.js","sourceRoot":"","sources":["../../src/adw/dialog.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoC,WAAW,EAAE,MAAM,OAAO,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAuB,MAAM,oCAAoC,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAItD,MAAM,WAAW,GAAG,CAAC,MAAkB,EAAQ,EAAE;IAC7C,UAAU,CAAC,GAAG,EAAE;QACZ,MAAM,CAAC,UAAU,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,GAAmC,EAAE;IAC1D,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IAEjC,OAAO,WAAW,CACd,CAAC,MAAkB,EAAE,EAAE;QACnB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC,EACD,CAAC,MAAM,CAAC,CACX,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,SAAsB,EAAgD,EAAE,CACnG,uBAAuB,CACnB,wBAAwB,CAAa,SAAS,EAAE;IAC5C,UAAU,EAAE,gBAAgB;IAC5B,OAAO,EAAE,WAAW;CACvB,CAAC,CACL,CAAC;AAEN,gBAAgB;AAChB,OAAO,EAAE,qBAAqB,EAAE,CAAC","sourcesContent":["import type * as Adw from \"@gtkx/gi/adw\";\nimport { type ElementType, type ReactNode, useCallback } from \"react\";\nimport { createPortaledComponent } from \"../components/portaled.js\";\nimport { useParentWindow } from \"../hooks/use-parent-window.js\";\nimport { createPresentedComponent, type PresentedProps } from \"../hooks/use-presented-instance.js\";\nimport { applyWrite } from \"../reconciler/signals.js\";\n\ntype DialogComponentProps = PresentedProps<Adw.Dialog>;\n\nconst closeDialog = (dialog: Adw.Dialog): void => {\n applyWrite(() => {\n dialog.forceClose();\n });\n};\n\nconst usePresentDialog = (): ((dialog: Adw.Dialog) => void) => {\n const parent = useParentWindow();\n\n return useCallback(\n (dialog: Adw.Dialog) => {\n dialog.present(parent);\n },\n [parent],\n );\n};\n\nconst createDialogComponent = (Component: ElementType): ((props: DialogComponentProps) => ReactNode) =>\n createPortaledComponent(\n createPresentedComponent<Adw.Dialog>(Component, {\n usePresent: usePresentDialog,\n dismiss: closeDialog,\n }),\n );\n\n/** @internal */\nexport { createDialogComponent };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/components/application.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAuC,MAAM,OAAO,CAAC;AAgF9F,QAAA,MAAM,0BAA0B,GAAI,WAAW,WAAW,KAAG,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,CAC3B,CAAC;AAEjE,gBAAgB;AAChB,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
1
+ {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/components/application.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAuC,MAAM,OAAO,CAAC;AA6F9F,QAAA,MAAM,0BAA0B,GAAI,WAAW,WAAW,KAAG,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,CAC3B,CAAC;AAEjE,gBAAgB;AAChB,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { quitApplication, runApplication } from "@gtkx/runtime";
3
- import { pickBy } from "@gtkx/utils";
3
+ import { pickBy, warn } from "@gtkx/utils";
4
4
  import process from "node:process";
5
5
  import { useLayoutEffect, useState } from "react";
6
6
  import { applicationId as defaultApplicationId } from "virtual:gtkx-config";
@@ -12,11 +12,20 @@ const commandLine = (applicationId) => [
12
12
  applicationId?.split(".").at(-1) ?? "gtkx",
13
13
  ...process.argv.slice(2),
14
14
  ];
15
+ const reportOwnedApplicationId = (application) => {
16
+ if (!application.getIsRegistered() || !application.getIsRemote()) {
17
+ return;
18
+ }
19
+ warn(`Another process already owns ${application.applicationId ?? "this application ID"}, so this process ` +
20
+ "registered as a remote instance and can never show a window. Quit that instance or change " +
21
+ "applicationId, then start this application again.");
22
+ };
15
23
  const startApplication = (application, setActivated, applicationId) => {
16
24
  application.on("activate", () => {
17
25
  setActivated(true);
18
26
  });
19
27
  const { exitStatus } = runApplication(application, commandLine(applicationId));
28
+ reportOwnedApplicationId(application);
20
29
  if (exitStatus !== 0) {
21
30
  process.exitCode = exitStatus;
22
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"application.js","sourceRoot":"","sources":["../../src/components/application.tsx"],"names":[],"mappings":"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","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { quitApplication, runApplication } from \"@gtkx/runtime\";\nimport { pickBy } from \"@gtkx/utils\";\nimport process from \"node:process\";\nimport { type ElementType, type ReactNode, type Ref, useLayoutEffect, useState } from \"react\";\nimport { applicationId as defaultApplicationId } from \"virtual:gtkx-config\";\nimport { ApplicationContext } from \"../hooks/use-application.js\";\nimport { useMergedRef } from \"../hooks/use-merged-refs.js\";\nimport { createPortaledComponent } from \"./portaled.js\";\n\ntype ApplicationComponentProps = {\n applicationId?: string | null | undefined;\n children?: ReactNode | undefined;\n ref?: Ref<Gtk.Application | null> | undefined;\n};\n\nconst POST_ACTIVATE_PROPS = new Set([\"menubar\"]);\n\nconst commandLine = (applicationId: string | null): string[] => [\n applicationId?.split(\".\").at(-1) ?? \"gtkx\",\n ...process.argv.slice(2),\n];\n\nconst startApplication = (\n application: Gtk.Application,\n setActivated: (isActivated: boolean) => void,\n applicationId: string | null,\n): void => {\n application.on(\"activate\", () => {\n setActivated(true);\n });\n\n const { exitStatus } = runApplication(application, commandLine(applicationId));\n\n if (exitStatus !== 0) {\n process.exitCode = exitStatus;\n }\n};\n\nconst useApplicationLifecycle = (\n application: Gtk.Application | null,\n setActivated: (isActivated: boolean) => void,\n applicationId: string | null,\n): void => {\n useLayoutEffect(() => {\n if (!application) {\n return;\n }\n\n startApplication(application, setActivated, applicationId);\n\n return () => {\n quitApplication(application);\n setActivated(false);\n };\n }, [application, setActivated, applicationId]);\n};\n\nconst applicationChildren = (application: Gtk.Application | null, children: ReactNode): ReactNode => {\n if (!application) {\n return null;\n }\n\n return <ApplicationContext.Provider value={application}>{children}</ApplicationContext.Provider>;\n};\n\nconst createApplicationElement = (\n Component: ElementType,\n): ((props: ApplicationComponentProps) => ReactNode) => {\n return ({ applicationId = defaultApplicationId, children, ref, ...rest }: ApplicationComponentProps): ReactNode => {\n const [application, setApplication] = useState<Gtk.Application | null>(null);\n const [activated, setActivated] = useState(false);\n useApplicationLifecycle(application, setActivated, applicationId);\n const mergedRef = useMergedRef(ref, setApplication);\n const appliedProps = activated ? rest : pickBy(rest, (_value, key) => !POST_ACTIVATE_PROPS.has(key));\n\n return (\n <Component ref={mergedRef} applicationId={applicationId} {...appliedProps}>\n {activated ? applicationChildren(application, children) : null}\n </Component>\n );\n };\n};\n\nconst createApplicationComponent = (Component: ElementType): ((props: unknown) => ReactNode) =>\n createPortaledComponent(createApplicationElement(Component));\n\n/** @internal */\nexport { createApplicationComponent };\n"]}
1
+ {"version":3,"file":"application.js","sourceRoot":"","sources":["../../src/components/application.tsx"],"names":[],"mappings":"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","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { quitApplication, runApplication } from \"@gtkx/runtime\";\nimport { pickBy, warn } from \"@gtkx/utils\";\nimport process from \"node:process\";\nimport { type ElementType, type ReactNode, type Ref, useLayoutEffect, useState } from \"react\";\nimport { applicationId as defaultApplicationId } from \"virtual:gtkx-config\";\nimport { ApplicationContext } from \"../hooks/use-application.js\";\nimport { useMergedRef } from \"../hooks/use-merged-refs.js\";\nimport { createPortaledComponent } from \"./portaled.js\";\n\ntype ApplicationComponentProps = {\n applicationId?: string | null | undefined;\n children?: ReactNode | undefined;\n ref?: Ref<Gtk.Application | null> | undefined;\n};\n\nconst POST_ACTIVATE_PROPS = new Set([\"menubar\"]);\n\nconst commandLine = (applicationId: string | null): string[] => [\n applicationId?.split(\".\").at(-1) ?? \"gtkx\",\n ...process.argv.slice(2),\n];\n\nconst reportOwnedApplicationId = (application: Gtk.Application): void => {\n if (!application.getIsRegistered() || !application.getIsRemote()) {\n return;\n }\n\n warn(\n `Another process already owns ${application.applicationId ?? \"this application ID\"}, so this process ` +\n \"registered as a remote instance and can never show a window. Quit that instance or change \" +\n \"applicationId, then start this application again.\",\n );\n};\n\nconst startApplication = (\n application: Gtk.Application,\n setActivated: (isActivated: boolean) => void,\n applicationId: string | null,\n): void => {\n application.on(\"activate\", () => {\n setActivated(true);\n });\n\n const { exitStatus } = runApplication(application, commandLine(applicationId));\n reportOwnedApplicationId(application);\n\n if (exitStatus !== 0) {\n process.exitCode = exitStatus;\n }\n};\n\nconst useApplicationLifecycle = (\n application: Gtk.Application | null,\n setActivated: (isActivated: boolean) => void,\n applicationId: string | null,\n): void => {\n useLayoutEffect(() => {\n if (!application) {\n return;\n }\n\n startApplication(application, setActivated, applicationId);\n\n return () => {\n quitApplication(application);\n setActivated(false);\n };\n }, [application, setActivated, applicationId]);\n};\n\nconst applicationChildren = (application: Gtk.Application | null, children: ReactNode): ReactNode => {\n if (!application) {\n return null;\n }\n\n return <ApplicationContext.Provider value={application}>{children}</ApplicationContext.Provider>;\n};\n\nconst createApplicationElement = (\n Component: ElementType,\n): ((props: ApplicationComponentProps) => ReactNode) => {\n return ({ applicationId = defaultApplicationId, children, ref, ...rest }: ApplicationComponentProps): ReactNode => {\n const [application, setApplication] = useState<Gtk.Application | null>(null);\n const [activated, setActivated] = useState(false);\n useApplicationLifecycle(application, setActivated, applicationId);\n const mergedRef = useMergedRef(ref, setApplication);\n const appliedProps = activated ? rest : pickBy(rest, (_value, key) => !POST_ACTIVATE_PROPS.has(key));\n\n return (\n <Component ref={mergedRef} applicationId={applicationId} {...appliedProps}>\n {activated ? applicationChildren(application, children) : null}\n </Component>\n );\n };\n};\n\nconst createApplicationComponent = (Component: ElementType): ((props: unknown) => ReactNode) =>\n createPortaledComponent(createApplicationElement(Component));\n\n/** @internal */\nexport { createApplicationComponent };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"host-config.d.ts","sourceRoot":"","sources":["../../src/reconciler/host-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAKjD,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAa/C,OAAO,EAOH,KAAK,QAAQ,EAGb,KAAK,QAAQ,EAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAUpE,+GAA+G;AAC/G,KAAK,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;AA0H9C,QAAA,MAAM,UAAU,EAAE,eAAe,CAAC,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CACrE,CAAC;AAgGhC,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"host-config.d.ts","sourceRoot":"","sources":["../../src/reconciler/host-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAKjD,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAc/C,OAAO,EAOH,KAAK,QAAQ,EAGb,KAAK,QAAQ,EAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAUpE,+GAA+G;AAC/G,KAAK,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;AA2H9C,QAAA,MAAM,UAAU,EAAE,eAAe,CAAC,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CACrE,CAAC;AAgGhC,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,CAAC"}
@@ -1,9 +1,10 @@
1
1
  import * as Gtk from "@gtkx/gi/gtk";
2
2
  import { getClassType, typeName } from "@gtkx/runtime";
3
- import { getOrInsert, packageVersion } from "@gtkx/utils";
3
+ import { getOrInsert } from "@gtkx/utils";
4
4
  import { createContext } from "react";
5
5
  import ReactReconciler from "react-reconciler";
6
6
  import { DefaultEventPriority, DiscreteEventPriority, NoEventPriority } from "react-reconciler/constants.js";
7
+ import packageManifest from "../../package.json" with { type: "json" };
7
8
  import { Prop } from "../components/element.js";
8
9
  import { applyAdoptedProps, applyElementProps, assertPropsCanChange, flushAccessible, flushBehaviors, } from "./apply-props.js";
9
10
  import { attachChild, detachChild } from "./child-routing.js";
@@ -12,12 +13,13 @@ import { createElementNode, createPropNode, createTextNode, ELEMENT_KIND, LAZY_K
12
13
  import { isRootElement } from "./root-element.js";
13
14
  import { disconnectAllHandlers } from "./signals.js";
14
15
  import { didUpdateTextSurgically, enclosingHost, flushTextHosts, markTextDirty, validateContentMix, } from "./text.js";
16
+ const RENDERER_VERSION = packageManifest.version;
15
17
  const HOST_CONTEXT = {};
16
18
  const containerNodes = new WeakMap();
17
19
  const priority = createPriorityTracker();
18
20
  const hostConfig = {
19
21
  rendererPackageName: "@gtkx/react",
20
- rendererVersion: packageVersion(import.meta.url, "@gtkx/react/package.json"),
22
+ rendererVersion: RENDERER_VERSION,
21
23
  supportsMutation: true,
22
24
  supportsPersistence: false,
23
25
  supportsHydration: false,
@@ -1 +1 @@
1
- {"version":3,"file":"host-config.js","sourceRoot":"","sources":["../../src/reconciler/host-config.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { type AnyClass, getClassType, typeName } from \"@gtkx/runtime\";\nimport { getOrInsert, packageVersion } from \"@gtkx/utils\";\nimport { createContext } from \"react\";\nimport ReactReconciler from \"react-reconciler\";\nimport { DefaultEventPriority, DiscreteEventPriority, NoEventPriority } from \"react-reconciler/constants.js\";\nimport type { Props } from \"./registry.js\";\nimport { Prop } from \"../components/element.js\";\nimport {\n applyAdoptedProps,\n applyElementProps,\n assertPropsCanChange,\n flushAccessible,\n flushBehaviors,\n} from \"./apply-props.js\";\nimport { attachChild, detachChild } from \"./child-routing.js\";\nimport { resolveElementNode } from \"./instance.js\";\nimport {\n type AnyNode,\n createElementNode,\n createPropNode,\n createTextNode,\n ELEMENT_KIND,\n type ElementNode,\n type Instance,\n LAZY_KIND,\n lazyTarget,\n type TextNode,\n} from \"./node.js\";\nimport { isRootElement, type RootElement } from \"./root-element.js\";\nimport { disconnectAllHandlers } from \"./signals.js\";\nimport {\n didUpdateTextSurgically,\n enclosingHost,\n flushTextHosts,\n markTextDirty,\n validateContentMix,\n} from \"./text.js\";\n\n/** What a tree is rendered into: any GObject, or the {@link RootElement} marker to render at the top level. */\ntype Container = RootElement | GObject.Object;\n\ntype PriorityTracker = {\n get: () => number;\n set: (priority: number) => void;\n withDiscrete: <T>(fn: () => T) => T;\n};\n\nconst HOST_CONTEXT: Record<string, never> = {};\nconst containerNodes: WeakMap<object, ElementNode> = new WeakMap();\nconst priority = createPriorityTracker();\n\nconst hostConfig = {\n rendererPackageName: \"@gtkx/react\",\n rendererVersion: packageVersion(import.meta.url, \"@gtkx/react/package.json\"),\n supportsMutation: true,\n supportsPersistence: false,\n supportsHydration: false,\n supportsMicrotasks: true,\n scheduleMicrotask: (fn: () => void): void => {\n queueMicrotask(fn);\n },\n isPrimaryRenderer: true,\n noTimeout: -1,\n scheduleTimeout: (fn: (...args: unknown[]) => unknown, delay?: number): ReturnType<typeof setTimeout> =>\n setTimeout(fn, delay),\n cancelTimeout: (id: ReturnType<typeof setTimeout>): void => {\n clearTimeout(id);\n },\n createInstance: (type: string, props: Props): Instance => createNode(type, props),\n createTextInstance: (text: string): TextNode => createTextNode(text),\n appendInitialChild: (parent: Instance, child: AnyNode): void => {\n attachChild(parent, child, null);\n },\n finalizeInitialChildren: (instance: Instance, _type: string, props: Props): boolean => {\n if (instance.kind === ELEMENT_KIND) {\n validateContentMix(instance, props);\n }\n\n return false;\n },\n shouldSetTextContent: (): boolean => false,\n getRootHostContext: (): Record<string, never> => HOST_CONTEXT,\n getChildHostContext: (parent: Record<string, never>): Record<string, never> => parent,\n getPublicInstance: (instance: Instance): object => getPublicInstance(instance),\n prepareForCommit: (): null => null,\n resetAfterCommit: (): void => {\n flushTextHosts();\n flushBehaviors();\n flushAccessible();\n },\n preparePortalMount: (): void => undefined,\n clearContainer: (): void => undefined,\n appendChild: (parent: Instance, child: AnyNode): void => {\n attachChild(parent, child, null);\n },\n appendChildToContainer: (container: Container, child: AnyNode): void => {\n attachToContainer(container, child, null);\n },\n insertBefore: (parent: Instance, child: AnyNode, before: AnyNode): void => {\n attachChild(parent, child, before);\n },\n insertInContainerBefore: (container: Container, child: AnyNode, before: AnyNode): void => {\n attachToContainer(container, child, before);\n },\n removeChild: (parent: Instance, child: AnyNode): void => {\n detachChild(parent, child);\n },\n removeChildFromContainer: (container: Container, child: AnyNode): void => {\n detachFromContainer(container, child);\n },\n commitTextUpdate: (textInstance: TextNode, oldText: string, newText: string): void => {\n textInstance.text = newText;\n const host = enclosingHost(textInstance);\n\n if (host !== null && !didUpdateTextSurgically(host, textInstance, oldText, newText)) {\n markTextDirty(host);\n }\n },\n commitUpdate: (instance: Instance, _type: string, prevProps: Props, nextProps: Props): void => {\n updateInstance(instance, prevProps, nextProps);\n },\n hideInstance: (instance: Instance): void => {\n setWidgetVisible(instance, false);\n },\n unhideInstance: (instance: Instance, props: Props): void => {\n setWidgetVisible(instance, props.visible !== false);\n },\n hideTextInstance: (): void => undefined,\n unhideTextInstance: (): void => undefined,\n detachDeletedInstance: (instance: Instance): void => {\n if (instance.kind === ELEMENT_KIND) {\n disconnectAllHandlers(instance);\n } else if (instance.kind === LAZY_KIND && instance.adopted !== null) {\n disconnectAllHandlers(lazyTarget(instance, instance.adopted));\n }\n },\n getInstanceFromNode: (): null => null,\n beforeActiveInstanceBlur: (): void => undefined,\n afterActiveInstanceBlur: (): void => undefined,\n prepareScopeUpdate: (): void => undefined,\n getInstanceFromScope: (): null => null,\n setCurrentUpdatePriority: (next: number): void => {\n priority.set(next);\n },\n getCurrentUpdatePriority: (): number => priority.get(),\n resolveUpdatePriority: (): number => (priority.get() === NoEventPriority ? DefaultEventPriority : priority.get()),\n resetFormInstance: (): void => undefined,\n requestPostPaintCallback: (): void => undefined,\n shouldAttemptEagerTransition: (): boolean => false,\n trackSchedulerEvent: (): void => undefined,\n resolveEventType: (): null => null,\n resolveEventTimeStamp: (): number => -1,\n maySuspendCommit: (): boolean => false,\n preloadInstance: (): boolean => true,\n startSuspendingCommit: (): void => undefined,\n suspendInstance: (): void => undefined,\n waitForCommitToBeReady: (): null => null,\n NotPendingTransition: null,\n HostTransitionContext: createContext(null) as unknown as ReactReconciler.ReactContext<null>,\n};\n\nconst reconciler: ReactReconciler.Reconciler<Container, Instance, TextNode, unknown, unknown, object> =\n ReactReconciler(hostConfig);\n\nfunction createPriorityTracker(): PriorityTracker {\n let current: number = NoEventPriority;\n\n return {\n get: () => current,\n set: (next) => {\n current = next;\n },\n withDiscrete: (fn) => {\n const previous = current;\n current = DiscreteEventPriority;\n\n try {\n return fn();\n } finally {\n current = previous;\n }\n },\n };\n}\n\nconst updateInstance = (instance: Instance, prev: Props, next: Props): void => {\n if (instance.kind === ELEMENT_KIND) {\n assertPropsCanChange(instance.typeName, prev, next);\n applyElementProps(instance, prev, next);\n\n return;\n }\n\n if (instance.kind === LAZY_KIND && instance.adopted !== null) {\n assertPropsCanChange(instance.typeName, prev, next);\n applyAdoptedProps(lazyTarget(instance, instance.adopted), prev, next);\n instance.props = next;\n }\n};\n\nconst attachToContainer = (container: Container, child: AnyNode, before: AnyNode | null): void => {\n if (!isRootElement(container)) {\n attachChild(getOrCreateContainerNode(container), child, before);\n }\n};\n\nconst detachFromContainer = (container: Container, child: AnyNode): void => {\n if (!isRootElement(container)) {\n detachChild(getOrCreateContainerNode(container), child);\n }\n};\n\nconst getPublicInstance = (instance: Instance): object => {\n if (instance.kind === ELEMENT_KIND) {\n return instance.object;\n }\n\n if (instance.kind === LAZY_KIND) {\n return instance.adopted ?? instance;\n }\n\n return instance;\n};\n\nconst setWidgetVisible = (instance: Instance, isVisible: boolean): void => {\n if (instance.kind === ELEMENT_KIND && instance.object instanceof Gtk.Widget) {\n instance.object.setVisible(isVisible);\n }\n};\n\nconst adoptContainer = (container: GObject.Object): ElementNode => {\n const name = typeName(getClassType(container.constructor as AnyClass));\n\n if (name === null) {\n throw new Error(\"Cannot adopt a container whose GType has no registered name\");\n }\n\n return createElementNode(name, container, priority.withDiscrete, null);\n};\n\nconst getOrCreateContainerNode = (container: GObject.Object): ElementNode =>\n getOrInsert(containerNodes, container, adoptContainer);\n\nconst createNode = (type: string, props: Props): Instance => {\n if (type === Prop) {\n return createPropNode(props.propName as string);\n }\n\n const node = resolveElementNode(type, props, priority.withDiscrete);\n\n if (node.kind === ELEMENT_KIND) {\n containerNodes.set(node.object, node);\n applyElementProps(node, {}, props);\n }\n\n return node;\n};\n\nexport { reconciler, type Container };\n"]}
1
+ {"version":3,"file":"host-config.js","sourceRoot":"","sources":["../../src/reconciler/host-config.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { type AnyClass, getClassType, typeName } from \"@gtkx/runtime\";\nimport { getOrInsert } from \"@gtkx/utils\";\nimport { createContext } from \"react\";\nimport ReactReconciler from \"react-reconciler\";\nimport { DefaultEventPriority, DiscreteEventPriority, NoEventPriority } from \"react-reconciler/constants.js\";\nimport type { Props } from \"./registry.js\";\nimport packageManifest from \"../../package.json\" with { type: \"json\" };\nimport { Prop } from \"../components/element.js\";\nimport {\n applyAdoptedProps,\n applyElementProps,\n assertPropsCanChange,\n flushAccessible,\n flushBehaviors,\n} from \"./apply-props.js\";\nimport { attachChild, detachChild } from \"./child-routing.js\";\nimport { resolveElementNode } from \"./instance.js\";\nimport {\n type AnyNode,\n createElementNode,\n createPropNode,\n createTextNode,\n ELEMENT_KIND,\n type ElementNode,\n type Instance,\n LAZY_KIND,\n lazyTarget,\n type TextNode,\n} from \"./node.js\";\nimport { isRootElement, type RootElement } from \"./root-element.js\";\nimport { disconnectAllHandlers } from \"./signals.js\";\nimport {\n didUpdateTextSurgically,\n enclosingHost,\n flushTextHosts,\n markTextDirty,\n validateContentMix,\n} from \"./text.js\";\n\n/** What a tree is rendered into: any GObject, or the {@link RootElement} marker to render at the top level. */\ntype Container = RootElement | GObject.Object;\n\ntype PriorityTracker = {\n get: () => number;\n set: (priority: number) => void;\n withDiscrete: <T>(fn: () => T) => T;\n};\n\nconst RENDERER_VERSION = packageManifest.version;\nconst HOST_CONTEXT: Record<string, never> = {};\nconst containerNodes: WeakMap<object, ElementNode> = new WeakMap();\nconst priority = createPriorityTracker();\n\nconst hostConfig = {\n rendererPackageName: \"@gtkx/react\",\n rendererVersion: RENDERER_VERSION,\n supportsMutation: true,\n supportsPersistence: false,\n supportsHydration: false,\n supportsMicrotasks: true,\n scheduleMicrotask: (fn: () => void): void => {\n queueMicrotask(fn);\n },\n isPrimaryRenderer: true,\n noTimeout: -1,\n scheduleTimeout: (fn: (...args: unknown[]) => unknown, delay?: number): ReturnType<typeof setTimeout> =>\n setTimeout(fn, delay),\n cancelTimeout: (id: ReturnType<typeof setTimeout>): void => {\n clearTimeout(id);\n },\n createInstance: (type: string, props: Props): Instance => createNode(type, props),\n createTextInstance: (text: string): TextNode => createTextNode(text),\n appendInitialChild: (parent: Instance, child: AnyNode): void => {\n attachChild(parent, child, null);\n },\n finalizeInitialChildren: (instance: Instance, _type: string, props: Props): boolean => {\n if (instance.kind === ELEMENT_KIND) {\n validateContentMix(instance, props);\n }\n\n return false;\n },\n shouldSetTextContent: (): boolean => false,\n getRootHostContext: (): Record<string, never> => HOST_CONTEXT,\n getChildHostContext: (parent: Record<string, never>): Record<string, never> => parent,\n getPublicInstance: (instance: Instance): object => getPublicInstance(instance),\n prepareForCommit: (): null => null,\n resetAfterCommit: (): void => {\n flushTextHosts();\n flushBehaviors();\n flushAccessible();\n },\n preparePortalMount: (): void => undefined,\n clearContainer: (): void => undefined,\n appendChild: (parent: Instance, child: AnyNode): void => {\n attachChild(parent, child, null);\n },\n appendChildToContainer: (container: Container, child: AnyNode): void => {\n attachToContainer(container, child, null);\n },\n insertBefore: (parent: Instance, child: AnyNode, before: AnyNode): void => {\n attachChild(parent, child, before);\n },\n insertInContainerBefore: (container: Container, child: AnyNode, before: AnyNode): void => {\n attachToContainer(container, child, before);\n },\n removeChild: (parent: Instance, child: AnyNode): void => {\n detachChild(parent, child);\n },\n removeChildFromContainer: (container: Container, child: AnyNode): void => {\n detachFromContainer(container, child);\n },\n commitTextUpdate: (textInstance: TextNode, oldText: string, newText: string): void => {\n textInstance.text = newText;\n const host = enclosingHost(textInstance);\n\n if (host !== null && !didUpdateTextSurgically(host, textInstance, oldText, newText)) {\n markTextDirty(host);\n }\n },\n commitUpdate: (instance: Instance, _type: string, prevProps: Props, nextProps: Props): void => {\n updateInstance(instance, prevProps, nextProps);\n },\n hideInstance: (instance: Instance): void => {\n setWidgetVisible(instance, false);\n },\n unhideInstance: (instance: Instance, props: Props): void => {\n setWidgetVisible(instance, props.visible !== false);\n },\n hideTextInstance: (): void => undefined,\n unhideTextInstance: (): void => undefined,\n detachDeletedInstance: (instance: Instance): void => {\n if (instance.kind === ELEMENT_KIND) {\n disconnectAllHandlers(instance);\n } else if (instance.kind === LAZY_KIND && instance.adopted !== null) {\n disconnectAllHandlers(lazyTarget(instance, instance.adopted));\n }\n },\n getInstanceFromNode: (): null => null,\n beforeActiveInstanceBlur: (): void => undefined,\n afterActiveInstanceBlur: (): void => undefined,\n prepareScopeUpdate: (): void => undefined,\n getInstanceFromScope: (): null => null,\n setCurrentUpdatePriority: (next: number): void => {\n priority.set(next);\n },\n getCurrentUpdatePriority: (): number => priority.get(),\n resolveUpdatePriority: (): number => (priority.get() === NoEventPriority ? DefaultEventPriority : priority.get()),\n resetFormInstance: (): void => undefined,\n requestPostPaintCallback: (): void => undefined,\n shouldAttemptEagerTransition: (): boolean => false,\n trackSchedulerEvent: (): void => undefined,\n resolveEventType: (): null => null,\n resolveEventTimeStamp: (): number => -1,\n maySuspendCommit: (): boolean => false,\n preloadInstance: (): boolean => true,\n startSuspendingCommit: (): void => undefined,\n suspendInstance: (): void => undefined,\n waitForCommitToBeReady: (): null => null,\n NotPendingTransition: null,\n HostTransitionContext: createContext(null) as unknown as ReactReconciler.ReactContext<null>,\n};\n\nconst reconciler: ReactReconciler.Reconciler<Container, Instance, TextNode, unknown, unknown, object> =\n ReactReconciler(hostConfig);\n\nfunction createPriorityTracker(): PriorityTracker {\n let current: number = NoEventPriority;\n\n return {\n get: () => current,\n set: (next) => {\n current = next;\n },\n withDiscrete: (fn) => {\n const previous = current;\n current = DiscreteEventPriority;\n\n try {\n return fn();\n } finally {\n current = previous;\n }\n },\n };\n}\n\nconst updateInstance = (instance: Instance, prev: Props, next: Props): void => {\n if (instance.kind === ELEMENT_KIND) {\n assertPropsCanChange(instance.typeName, prev, next);\n applyElementProps(instance, prev, next);\n\n return;\n }\n\n if (instance.kind === LAZY_KIND && instance.adopted !== null) {\n assertPropsCanChange(instance.typeName, prev, next);\n applyAdoptedProps(lazyTarget(instance, instance.adopted), prev, next);\n instance.props = next;\n }\n};\n\nconst attachToContainer = (container: Container, child: AnyNode, before: AnyNode | null): void => {\n if (!isRootElement(container)) {\n attachChild(getOrCreateContainerNode(container), child, before);\n }\n};\n\nconst detachFromContainer = (container: Container, child: AnyNode): void => {\n if (!isRootElement(container)) {\n detachChild(getOrCreateContainerNode(container), child);\n }\n};\n\nconst getPublicInstance = (instance: Instance): object => {\n if (instance.kind === ELEMENT_KIND) {\n return instance.object;\n }\n\n if (instance.kind === LAZY_KIND) {\n return instance.adopted ?? instance;\n }\n\n return instance;\n};\n\nconst setWidgetVisible = (instance: Instance, isVisible: boolean): void => {\n if (instance.kind === ELEMENT_KIND && instance.object instanceof Gtk.Widget) {\n instance.object.setVisible(isVisible);\n }\n};\n\nconst adoptContainer = (container: GObject.Object): ElementNode => {\n const name = typeName(getClassType(container.constructor as AnyClass));\n\n if (name === null) {\n throw new Error(\"Cannot adopt a container whose GType has no registered name\");\n }\n\n return createElementNode(name, container, priority.withDiscrete, null);\n};\n\nconst getOrCreateContainerNode = (container: GObject.Object): ElementNode =>\n getOrInsert(containerNodes, container, adoptContainer);\n\nconst createNode = (type: string, props: Props): Instance => {\n if (type === Prop) {\n return createPropNode(props.propName as string);\n }\n\n const node = resolveElementNode(type, props, priority.withDiscrete);\n\n if (node.kind === ELEMENT_KIND) {\n containerNodes.set(node.object, node);\n applyElementProps(node, {}, props);\n }\n\n return node;\n};\n\nexport { reconciler, type Container };\n"]}
@@ -11,14 +11,20 @@ type ReconcilerRootOptions = RootErrorCallbacks & {
11
11
  };
12
12
  /** A render root whose updates and teardown the caller drives, with error handling left to it. */
13
13
  type ReconcilerRoot = {
14
- /** Mounts an element tree into the container, or updates the tree already mounted there. */
14
+ /**
15
+ * Mounts an element tree into the container, or updates the tree already mounted there. Passing `null` unmounts
16
+ * the container instead.
17
+ */
15
18
  update: (element: ReactNode) => void;
16
19
  /** Hands the root to `teardown`, then stops {@link quit} from unmounting the container. */
17
20
  unmount: (teardown: (root: ReconcilerRoot) => Promise<void>) => Promise<void>;
18
21
  };
19
22
  /** The object {@link createRoot} returns: it renders an element tree into a container and can tear it down. */
20
23
  type Root = {
21
- /** Mounts an element tree into the container, or updates the tree already mounted there. */
24
+ /**
25
+ * Mounts an element tree into the container, or updates the tree already mounted there. Rendering `null` unmounts
26
+ * the container instead.
27
+ */
22
28
  render: (element: ReactNode) => void;
23
29
  /** Unmounts the rendered tree and runs its effect cleanups. */
24
30
  unmount: () => void;
@@ -33,8 +39,13 @@ declare const createReconcilerRoot: (options: ReconcilerRootOptions) => Reconcil
33
39
  * @param container The GObject to render into; defaults to the shared {@link rootElement}, which holds no object.
34
40
  */
35
41
  declare const createRoot: (container?: Container) => Root;
36
- /** Unmounts every active render root and stops the originating signal from propagating further. */
37
- declare const quit: () => typeof Gdk.EVENT_STOP;
42
+ /**
43
+ * Unmounts every render root that currently holds a mounted tree.
44
+ *
45
+ * @returns `Gdk.EVENT_STOP` when at least one root came down, so a close-request handler keeps GTK4 from closing the
46
+ * window itself, and `Gdk.EVENT_PROPAGATE` when there was nothing to unmount, so the default handler still runs.
47
+ */
48
+ declare const quit: () => typeof Gdk.EVENT_PROPAGATE | typeof Gdk.EVENT_STOP;
38
49
  /**
39
50
  * Renders children into a container other than the surrounding tree.
40
51
  *
@@ -1 +1 @@
1
- {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/reconciler/root.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC/D,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAIpC,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,kBAAkB,CAAC;AAK9D,KAAK,kBAAkB,GAAG;IACtB,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5D,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1D,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;CAClE,CAAC;AAEF,KAAK,qBAAqB,GAAG,kBAAkB,GAAG;IAAE,aAAa,EAAE,SAAS,CAAA;CAAE,CAAC;AAE/E,kGAAkG;AAClG,KAAK,cAAc,GAAG;IAClB,4FAA4F;IAC5F,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,2FAA2F;IAC3F,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjF,CAAC;AAEF,+GAA+G;AAC/G,KAAK,IAAI,GAAG;IACR,4FAA4F;IAC5F,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,+DAA+D;IAC/D,OAAO,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAEF,KAAK,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;AAsB7C,QAAA,MAAM,yBAAyB,GAAI,SAAS,YAAY,KAAG,YAAY,GAAG,IAAqC,CAAC;AA4ChH,QAAA,MAAM,oBAAoB,GAAI,SAAS,qBAAqB,KAAG,cAc9D,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,UAAU,GAAI,YAAW,SAAuB,KAAG,IAcxD,CAAC;AAEF,mGAAmG;AACnG,QAAA,MAAM,IAAI,QAAO,OAAO,GAAG,CAAC,UAM3B,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,YAAY,GAAI,UAAU,SAAS,EAAE,WAAW,SAAS,EAAE,MAAM,MAAM,KAAG,WACa,CAAC;AAE9F,OAAO,EACH,yBAAyB,EACzB,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,YAAY,EACZ,KAAK,cAAc,EACnB,KAAK,IAAI,GACZ,CAAC"}
1
+ {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/reconciler/root.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC/D,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAIpC,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,kBAAkB,CAAC;AAK9D,KAAK,kBAAkB,GAAG;IACtB,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5D,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1D,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;CAClE,CAAC;AAEF,KAAK,qBAAqB,GAAG,kBAAkB,GAAG;IAAE,aAAa,EAAE,SAAS,CAAA;CAAE,CAAC;AAE/E,kGAAkG;AAClG,KAAK,cAAc,GAAG;IAClB;;;OAGG;IACH,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,2FAA2F;IAC3F,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjF,CAAC;AAEF,+GAA+G;AAC/G,KAAK,IAAI,GAAG;IACR;;;OAGG;IACH,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,+DAA+D;IAC/D,OAAO,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAEF,KAAK,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;AAsB7C,QAAA,MAAM,yBAAyB,GAAI,SAAS,YAAY,KAAG,YAAY,GAAG,IAAqC,CAAC;AAmDhH,QAAA,MAAM,oBAAoB,GAAI,SAAS,qBAAqB,KAAG,cAc9D,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,UAAU,GAAI,YAAW,SAAuB,KAAG,IAcxD,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,IAAI,QAAO,OAAO,GAAG,CAAC,eAAe,GAAG,OAAO,GAAG,CAAC,UAQxD,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,YAAY,GAAI,UAAU,SAAS,EAAE,WAAW,SAAS,EAAE,MAAM,MAAM,KAAG,WACa,CAAC;AAE9F,OAAO,EACH,yBAAyB,EACzB,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,YAAY,EACZ,KAAK,cAAc,EACnB,KAAK,IAAI,GACZ,CAAC"}
@@ -27,7 +27,7 @@ const logCaughtRenderError = (error) => {
27
27
  };
28
28
  const openContainer = (containerInfo, callbacks) => {
29
29
  injectIntoDevTools(reconciler);
30
- const container = reconciler.createContainer(containerInfo, ConcurrentRoot, null, false, null, "", (error, info) => {
30
+ return reconciler.createContainer(containerInfo, ConcurrentRoot, null, false, null, "", (error, info) => {
31
31
  errorHandlerSlot.get()?.(error);
32
32
  callbacks.onUncaughtError?.(error, info);
33
33
  }, (error, info) => {
@@ -36,18 +36,24 @@ const openContainer = (containerInfo, callbacks) => {
36
36
  }, (error, info) => {
37
37
  callbacks.onRecoverableError?.(error, info);
38
38
  }, () => undefined);
39
- activeRoots.add(container);
40
- return container;
41
39
  };
42
40
  const unmountContainer = (container) => {
43
41
  reconciler.updateContainer(null, container, null, null);
44
42
  activeRoots.delete(container);
45
43
  };
44
+ const mountContainer = (container, element) => {
45
+ if (element === null) {
46
+ unmountContainer(container);
47
+ return;
48
+ }
49
+ activeRoots.add(container);
50
+ reconciler.updateContainer(element, container, null, null);
51
+ };
46
52
  const createReconcilerRoot = (options) => {
47
53
  const container = openContainer(options.containerInfo, options);
48
54
  const root = {
49
55
  update: (element) => {
50
- reconciler.updateContainer(element, container, null, null);
56
+ mountContainer(container, element);
51
57
  },
52
58
  unmount: async (teardown) => {
53
59
  await teardown(root);
@@ -69,19 +75,25 @@ const createRoot = (container = rootElement) => {
69
75
  });
70
76
  return {
71
77
  render: (element) => {
72
- reconciler.updateContainer(element, opaque, null, null);
78
+ mountContainer(opaque, element);
73
79
  },
74
80
  unmount: () => {
75
81
  unmountContainer(opaque);
76
82
  },
77
83
  };
78
84
  };
79
- /** Unmounts every active render root and stops the originating signal from propagating further. */
85
+ /**
86
+ * Unmounts every render root that currently holds a mounted tree.
87
+ *
88
+ * @returns `Gdk.EVENT_STOP` when at least one root came down, so a close-request handler keeps GTK4 from closing the
89
+ * window itself, and `Gdk.EVENT_PROPAGATE` when there was nothing to unmount, so the default handler still runs.
90
+ */
80
91
  const quit = () => {
81
- for (const container of activeRoots) {
92
+ const containers = [...activeRoots];
93
+ for (const container of containers) {
82
94
  unmountContainer(container);
83
95
  }
84
- return Gdk.EVENT_STOP;
96
+ return containers.length > 0 ? Gdk.EVENT_STOP : Gdk.EVENT_PROPAGATE;
85
97
  };
86
98
  /**
87
99
  * Renders children into a container other than the surrounding tree.
@@ -1 +1 @@
1
- {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/reconciler/root.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ErrorInfo, ReactNode, ReactPortal } from \"react\";\nimport * as Gdk from \"@gtkx/gi/gdk\";\nimport { createLogger, type Logger } from \"@gtkx/utils\";\nimport { ConcurrentRoot } from \"react-reconciler/constants.js\";\nimport { injectIntoDevTools } from \"./devtools.js\";\nimport { type Container, reconciler } from \"./host-config.js\";\nimport { rootElement } from \"./root-element.js\";\n\ntype OpaqueRoot = { [opaqueRoot]: true };\n\ntype RootErrorCallbacks = {\n onUncaughtError?: (error: unknown, info: ErrorInfo) => void;\n onCaughtError?: (error: unknown, info: ErrorInfo) => void;\n onRecoverableError?: (error: unknown, info: ErrorInfo) => void;\n};\n\ntype ReconcilerRootOptions = RootErrorCallbacks & { containerInfo: Container };\n\n/** A render root whose updates and teardown the caller drives, with error handling left to it. */\ntype ReconcilerRoot = {\n /** Mounts an element tree into the container, or updates the tree already mounted there. */\n update: (element: ReactNode) => void;\n /** Hands the root to `teardown`, then stops {@link quit} from unmounting the container. */\n unmount: (teardown: (root: ReconcilerRoot) => Promise<void>) => Promise<void>;\n};\n\n/** The object {@link createRoot} returns: it renders an element tree into a container and can tear it down. */\ntype Root = {\n /** Mounts an element tree into the container, or updates the tree already mounted there. */\n render: (element: ReactNode) => void;\n /** Unmounts the rendered tree and runs its effect cleanups. */\n unmount: () => void;\n};\n\ntype ErrorHandler = (error: unknown) => void;\ntype ErrorHandlerSlot = { get: () => ErrorHandler | null; set: (handler: ErrorHandler) => ErrorHandler | null };\n\ndeclare const opaqueRoot: unique symbol;\nconst log: Logger = createLogger(\"react\");\nconst activeRoots: Set<OpaqueRoot> = new Set();\nconst errorHandlerSlot = createErrorHandlerSlot();\n\nfunction createErrorHandlerSlot(): ErrorHandlerSlot {\n let current: ErrorHandler | null = null;\n\n return {\n get: () => current,\n set: (handler) => {\n const previous = current;\n current = handler;\n\n return previous;\n },\n };\n}\n\nconst setReconcilerErrorHandler = (handler: ErrorHandler): ErrorHandler | null => errorHandlerSlot.set(handler);\n\nconst rethrowUncaughtRenderError = (error: unknown): never => {\n throw error;\n};\n\nconst logCaughtRenderError = (error: unknown): void => {\n log.error(\"caught render error\", error);\n};\n\nconst openContainer = (containerInfo: Container, callbacks: RootErrorCallbacks): OpaqueRoot => {\n injectIntoDevTools(reconciler);\n\n const container = reconciler.createContainer(\n containerInfo,\n ConcurrentRoot,\n null,\n false,\n null,\n \"\",\n (error, info) => {\n errorHandlerSlot.get()?.(error);\n callbacks.onUncaughtError?.(error, info);\n },\n (error, info) => {\n errorHandlerSlot.get()?.(error);\n callbacks.onCaughtError?.(error, info);\n },\n (error, info) => {\n callbacks.onRecoverableError?.(error, info);\n },\n (): void => undefined,\n ) as OpaqueRoot;\n\n activeRoots.add(container);\n\n return container;\n};\n\nconst unmountContainer = (container: OpaqueRoot): void => {\n reconciler.updateContainer(null, container, null, null);\n activeRoots.delete(container);\n};\n\nconst createReconcilerRoot = (options: ReconcilerRootOptions): ReconcilerRoot => {\n const container = openContainer(options.containerInfo, options);\n\n const root: ReconcilerRoot = {\n update: (element) => {\n reconciler.updateContainer(element, container, null, null);\n },\n unmount: async (teardown) => {\n await teardown(root);\n activeRoots.delete(container);\n },\n };\n\n return root;\n};\n\n/**\n * Creates a render root for a GTKX application. Uncaught render errors are rethrown and errors caught by an\n * error boundary are logged.\n *\n * @param container The GObject to render into; defaults to the shared {@link rootElement}, which holds no object.\n */\nconst createRoot = (container: Container = rootElement): Root => {\n const opaque = openContainer(container, {\n onUncaughtError: rethrowUncaughtRenderError,\n onCaughtError: logCaughtRenderError,\n });\n\n return {\n render: (element) => {\n reconciler.updateContainer(element, opaque, null, null);\n },\n unmount: () => {\n unmountContainer(opaque);\n },\n };\n};\n\n/** Unmounts every active render root and stops the originating signal from propagating further. */\nconst quit = (): typeof Gdk.EVENT_STOP => {\n for (const container of activeRoots) {\n unmountContainer(container);\n }\n\n return Gdk.EVENT_STOP;\n};\n\n/**\n * Renders children into a container other than the surrounding tree.\n *\n * @param container The GObject to render into, or {@link rootElement} to render at the top level.\n */\nconst createPortal = (children: ReactNode, container: Container, key?: string): ReactPortal =>\n reconciler.createPortal(children, container, null, key ?? null) as unknown as ReactPortal;\n\nexport {\n setReconcilerErrorHandler,\n createReconcilerRoot,\n createRoot,\n quit,\n createPortal,\n type ReconcilerRoot,\n type Root,\n};\n"]}
1
+ {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/reconciler/root.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ErrorInfo, ReactNode, ReactPortal } from \"react\";\nimport * as Gdk from \"@gtkx/gi/gdk\";\nimport { createLogger, type Logger } from \"@gtkx/utils\";\nimport { ConcurrentRoot } from \"react-reconciler/constants.js\";\nimport { injectIntoDevTools } from \"./devtools.js\";\nimport { type Container, reconciler } from \"./host-config.js\";\nimport { rootElement } from \"./root-element.js\";\n\ntype OpaqueRoot = { [opaqueRoot]: true };\n\ntype RootErrorCallbacks = {\n onUncaughtError?: (error: unknown, info: ErrorInfo) => void;\n onCaughtError?: (error: unknown, info: ErrorInfo) => void;\n onRecoverableError?: (error: unknown, info: ErrorInfo) => void;\n};\n\ntype ReconcilerRootOptions = RootErrorCallbacks & { containerInfo: Container };\n\n/** A render root whose updates and teardown the caller drives, with error handling left to it. */\ntype ReconcilerRoot = {\n /**\n * Mounts an element tree into the container, or updates the tree already mounted there. Passing `null` unmounts\n * the container instead.\n */\n update: (element: ReactNode) => void;\n /** Hands the root to `teardown`, then stops {@link quit} from unmounting the container. */\n unmount: (teardown: (root: ReconcilerRoot) => Promise<void>) => Promise<void>;\n};\n\n/** The object {@link createRoot} returns: it renders an element tree into a container and can tear it down. */\ntype Root = {\n /**\n * Mounts an element tree into the container, or updates the tree already mounted there. Rendering `null` unmounts\n * the container instead.\n */\n render: (element: ReactNode) => void;\n /** Unmounts the rendered tree and runs its effect cleanups. */\n unmount: () => void;\n};\n\ntype ErrorHandler = (error: unknown) => void;\ntype ErrorHandlerSlot = { get: () => ErrorHandler | null; set: (handler: ErrorHandler) => ErrorHandler | null };\n\ndeclare const opaqueRoot: unique symbol;\nconst log: Logger = createLogger(\"react\");\nconst activeRoots: Set<OpaqueRoot> = new Set();\nconst errorHandlerSlot = createErrorHandlerSlot();\n\nfunction createErrorHandlerSlot(): ErrorHandlerSlot {\n let current: ErrorHandler | null = null;\n\n return {\n get: () => current,\n set: (handler) => {\n const previous = current;\n current = handler;\n\n return previous;\n },\n };\n}\n\nconst setReconcilerErrorHandler = (handler: ErrorHandler): ErrorHandler | null => errorHandlerSlot.set(handler);\n\nconst rethrowUncaughtRenderError = (error: unknown): never => {\n throw error;\n};\n\nconst logCaughtRenderError = (error: unknown): void => {\n log.error(\"caught render error\", error);\n};\n\nconst openContainer = (containerInfo: Container, callbacks: RootErrorCallbacks): OpaqueRoot => {\n injectIntoDevTools(reconciler);\n\n return reconciler.createContainer(\n containerInfo,\n ConcurrentRoot,\n null,\n false,\n null,\n \"\",\n (error, info) => {\n errorHandlerSlot.get()?.(error);\n callbacks.onUncaughtError?.(error, info);\n },\n (error, info) => {\n errorHandlerSlot.get()?.(error);\n callbacks.onCaughtError?.(error, info);\n },\n (error, info) => {\n callbacks.onRecoverableError?.(error, info);\n },\n (): void => undefined,\n ) as OpaqueRoot;\n};\n\nconst unmountContainer = (container: OpaqueRoot): void => {\n reconciler.updateContainer(null, container, null, null);\n activeRoots.delete(container);\n};\n\nconst mountContainer = (container: OpaqueRoot, element: ReactNode): void => {\n if (element === null) {\n unmountContainer(container);\n\n return;\n }\n\n activeRoots.add(container);\n reconciler.updateContainer(element, container, null, null);\n};\n\nconst createReconcilerRoot = (options: ReconcilerRootOptions): ReconcilerRoot => {\n const container = openContainer(options.containerInfo, options);\n\n const root: ReconcilerRoot = {\n update: (element) => {\n mountContainer(container, element);\n },\n unmount: async (teardown) => {\n await teardown(root);\n activeRoots.delete(container);\n },\n };\n\n return root;\n};\n\n/**\n * Creates a render root for a GTKX application. Uncaught render errors are rethrown and errors caught by an\n * error boundary are logged.\n *\n * @param container The GObject to render into; defaults to the shared {@link rootElement}, which holds no object.\n */\nconst createRoot = (container: Container = rootElement): Root => {\n const opaque = openContainer(container, {\n onUncaughtError: rethrowUncaughtRenderError,\n onCaughtError: logCaughtRenderError,\n });\n\n return {\n render: (element) => {\n mountContainer(opaque, element);\n },\n unmount: () => {\n unmountContainer(opaque);\n },\n };\n};\n\n/**\n * Unmounts every render root that currently holds a mounted tree.\n *\n * @returns `Gdk.EVENT_STOP` when at least one root came down, so a close-request handler keeps GTK4 from closing the\n * window itself, and `Gdk.EVENT_PROPAGATE` when there was nothing to unmount, so the default handler still runs.\n */\nconst quit = (): typeof Gdk.EVENT_PROPAGATE | typeof Gdk.EVENT_STOP => {\n const containers = [...activeRoots];\n\n for (const container of containers) {\n unmountContainer(container);\n }\n\n return containers.length > 0 ? Gdk.EVENT_STOP : Gdk.EVENT_PROPAGATE;\n};\n\n/**\n * Renders children into a container other than the surrounding tree.\n *\n * @param container The GObject to render into, or {@link rootElement} to render at the top level.\n */\nconst createPortal = (children: ReactNode, container: Container, key?: string): ReactPortal =>\n reconciler.createPortal(children, container, null, key ?? null) as unknown as ReactPortal;\n\nexport {\n setReconcilerErrorHandler,\n createReconcilerRoot,\n createRoot,\n quit,\n createPortal,\n type ReconcilerRoot,\n type Root,\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/react",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "React reconciler that renders GTK4 object trees, with the portals, signal handling, and hooks GTKX apps use",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -71,14 +71,24 @@
71
71
  "!**/*.tsbuildinfo",
72
72
  "env.d.ts"
73
73
  ],
74
+ "nx": {
75
+ "targets": {
76
+ "lint": {
77
+ "options": {
78
+ "cwd": ".",
79
+ "command": "eslint {projectRoot}"
80
+ }
81
+ }
82
+ }
83
+ },
74
84
  "engines": {
75
85
  "node": ">=24"
76
86
  },
77
87
  "dependencies": {
78
88
  "react-reconciler": "^0.33.0",
79
- "@gtkx/config": "1.0.0",
80
- "@gtkx/runtime": "1.0.0",
81
- "@gtkx/utils": "1.0.0"
89
+ "@gtkx/config": "1.1.0",
90
+ "@gtkx/runtime": "1.1.0",
91
+ "@gtkx/utils": "1.1.0"
82
92
  },
83
93
  "devDependencies": {
84
94
  "@types/react": "^19.2.18",
@@ -3,11 +3,14 @@ import { type ElementType, type ReactNode, useCallback } from "react";
3
3
  import { createPortaledComponent } from "../components/portaled.js";
4
4
  import { useParentWindow } from "../hooks/use-parent-window.js";
5
5
  import { createPresentedComponent, type PresentedProps } from "../hooks/use-presented-instance.js";
6
+ import { applyWrite } from "../reconciler/signals.js";
6
7
 
7
8
  type DialogComponentProps = PresentedProps<Adw.Dialog>;
8
9
 
9
10
  const closeDialog = (dialog: Adw.Dialog): void => {
10
- dialog.forceClose();
11
+ applyWrite(() => {
12
+ dialog.forceClose();
13
+ });
11
14
  };
12
15
 
13
16
  const usePresentDialog = (): ((dialog: Adw.Dialog) => void) => {
@@ -1,6 +1,6 @@
1
1
  import type * as Gtk from "@gtkx/gi/gtk";
2
2
  import { quitApplication, runApplication } from "@gtkx/runtime";
3
- import { pickBy } from "@gtkx/utils";
3
+ import { pickBy, warn } from "@gtkx/utils";
4
4
  import process from "node:process";
5
5
  import { type ElementType, type ReactNode, type Ref, useLayoutEffect, useState } from "react";
6
6
  import { applicationId as defaultApplicationId } from "virtual:gtkx-config";
@@ -21,6 +21,18 @@ const commandLine = (applicationId: string | null): string[] => [
21
21
  ...process.argv.slice(2),
22
22
  ];
23
23
 
24
+ const reportOwnedApplicationId = (application: Gtk.Application): void => {
25
+ if (!application.getIsRegistered() || !application.getIsRemote()) {
26
+ return;
27
+ }
28
+
29
+ warn(
30
+ `Another process already owns ${application.applicationId ?? "this application ID"}, so this process ` +
31
+ "registered as a remote instance and can never show a window. Quit that instance or change " +
32
+ "applicationId, then start this application again.",
33
+ );
34
+ };
35
+
24
36
  const startApplication = (
25
37
  application: Gtk.Application,
26
38
  setActivated: (isActivated: boolean) => void,
@@ -31,6 +43,7 @@ const startApplication = (
31
43
  });
32
44
 
33
45
  const { exitStatus } = runApplication(application, commandLine(applicationId));
46
+ reportOwnedApplicationId(application);
34
47
 
35
48
  if (exitStatus !== 0) {
36
49
  process.exitCode = exitStatus;
@@ -1,11 +1,12 @@
1
1
  import type * as GObject from "@gtkx/gi/gobject";
2
2
  import * as Gtk from "@gtkx/gi/gtk";
3
3
  import { type AnyClass, getClassType, typeName } from "@gtkx/runtime";
4
- import { getOrInsert, packageVersion } from "@gtkx/utils";
4
+ import { getOrInsert } from "@gtkx/utils";
5
5
  import { createContext } from "react";
6
6
  import ReactReconciler from "react-reconciler";
7
7
  import { DefaultEventPriority, DiscreteEventPriority, NoEventPriority } from "react-reconciler/constants.js";
8
8
  import type { Props } from "./registry.js";
9
+ import packageManifest from "../../package.json" with { type: "json" };
9
10
  import { Prop } from "../components/element.js";
10
11
  import {
11
12
  applyAdoptedProps,
@@ -47,13 +48,14 @@ type PriorityTracker = {
47
48
  withDiscrete: <T>(fn: () => T) => T;
48
49
  };
49
50
 
51
+ const RENDERER_VERSION = packageManifest.version;
50
52
  const HOST_CONTEXT: Record<string, never> = {};
51
53
  const containerNodes: WeakMap<object, ElementNode> = new WeakMap();
52
54
  const priority = createPriorityTracker();
53
55
 
54
56
  const hostConfig = {
55
57
  rendererPackageName: "@gtkx/react",
56
- rendererVersion: packageVersion(import.meta.url, "@gtkx/react/package.json"),
58
+ rendererVersion: RENDERER_VERSION,
57
59
  supportsMutation: true,
58
60
  supportsPersistence: false,
59
61
  supportsHydration: false,
@@ -18,7 +18,10 @@ type ReconcilerRootOptions = RootErrorCallbacks & { containerInfo: Container };
18
18
 
19
19
  /** A render root whose updates and teardown the caller drives, with error handling left to it. */
20
20
  type ReconcilerRoot = {
21
- /** Mounts an element tree into the container, or updates the tree already mounted there. */
21
+ /**
22
+ * Mounts an element tree into the container, or updates the tree already mounted there. Passing `null` unmounts
23
+ * the container instead.
24
+ */
22
25
  update: (element: ReactNode) => void;
23
26
  /** Hands the root to `teardown`, then stops {@link quit} from unmounting the container. */
24
27
  unmount: (teardown: (root: ReconcilerRoot) => Promise<void>) => Promise<void>;
@@ -26,7 +29,10 @@ type ReconcilerRoot = {
26
29
 
27
30
  /** The object {@link createRoot} returns: it renders an element tree into a container and can tear it down. */
28
31
  type Root = {
29
- /** Mounts an element tree into the container, or updates the tree already mounted there. */
32
+ /**
33
+ * Mounts an element tree into the container, or updates the tree already mounted there. Rendering `null` unmounts
34
+ * the container instead.
35
+ */
30
36
  render: (element: ReactNode) => void;
31
37
  /** Unmounts the rendered tree and runs its effect cleanups. */
32
38
  unmount: () => void;
@@ -67,7 +73,7 @@ const logCaughtRenderError = (error: unknown): void => {
67
73
  const openContainer = (containerInfo: Container, callbacks: RootErrorCallbacks): OpaqueRoot => {
68
74
  injectIntoDevTools(reconciler);
69
75
 
70
- const container = reconciler.createContainer(
76
+ return reconciler.createContainer(
71
77
  containerInfo,
72
78
  ConcurrentRoot,
73
79
  null,
@@ -87,10 +93,6 @@ const openContainer = (containerInfo: Container, callbacks: RootErrorCallbacks):
87
93
  },
88
94
  (): void => undefined,
89
95
  ) as OpaqueRoot;
90
-
91
- activeRoots.add(container);
92
-
93
- return container;
94
96
  };
95
97
 
96
98
  const unmountContainer = (container: OpaqueRoot): void => {
@@ -98,12 +100,23 @@ const unmountContainer = (container: OpaqueRoot): void => {
98
100
  activeRoots.delete(container);
99
101
  };
100
102
 
103
+ const mountContainer = (container: OpaqueRoot, element: ReactNode): void => {
104
+ if (element === null) {
105
+ unmountContainer(container);
106
+
107
+ return;
108
+ }
109
+
110
+ activeRoots.add(container);
111
+ reconciler.updateContainer(element, container, null, null);
112
+ };
113
+
101
114
  const createReconcilerRoot = (options: ReconcilerRootOptions): ReconcilerRoot => {
102
115
  const container = openContainer(options.containerInfo, options);
103
116
 
104
117
  const root: ReconcilerRoot = {
105
118
  update: (element) => {
106
- reconciler.updateContainer(element, container, null, null);
119
+ mountContainer(container, element);
107
120
  },
108
121
  unmount: async (teardown) => {
109
122
  await teardown(root);
@@ -128,7 +141,7 @@ const createRoot = (container: Container = rootElement): Root => {
128
141
 
129
142
  return {
130
143
  render: (element) => {
131
- reconciler.updateContainer(element, opaque, null, null);
144
+ mountContainer(opaque, element);
132
145
  },
133
146
  unmount: () => {
134
147
  unmountContainer(opaque);
@@ -136,13 +149,20 @@ const createRoot = (container: Container = rootElement): Root => {
136
149
  };
137
150
  };
138
151
 
139
- /** Unmounts every active render root and stops the originating signal from propagating further. */
140
- const quit = (): typeof Gdk.EVENT_STOP => {
141
- for (const container of activeRoots) {
152
+ /**
153
+ * Unmounts every render root that currently holds a mounted tree.
154
+ *
155
+ * @returns `Gdk.EVENT_STOP` when at least one root came down, so a close-request handler keeps GTK4 from closing the
156
+ * window itself, and `Gdk.EVENT_PROPAGATE` when there was nothing to unmount, so the default handler still runs.
157
+ */
158
+ const quit = (): typeof Gdk.EVENT_PROPAGATE | typeof Gdk.EVENT_STOP => {
159
+ const containers = [...activeRoots];
160
+
161
+ for (const container of containers) {
142
162
  unmountContainer(container);
143
163
  }
144
164
 
145
- return Gdk.EVENT_STOP;
165
+ return containers.length > 0 ? Gdk.EVENT_STOP : Gdk.EVENT_PROPAGATE;
146
166
  };
147
167
 
148
168
  /**