@gtkx/react 1.0.0-rc.1 → 1.0.0-rc.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/dist/adw/config.d.ts +2 -0
- package/dist/adw/config.d.ts.map +1 -0
- package/dist/adw/config.js +2 -0
- package/dist/adw/config.js.map +1 -0
- package/dist/{libraries/adw → adw}/dialog.d.ts +2 -2
- package/dist/adw/dialog.d.ts.map +1 -0
- package/dist/adw/dialog.js +25 -0
- package/dist/adw/dialog.js.map +1 -0
- package/dist/adw/element-behaviors.d.ts +2 -0
- package/dist/adw/element-behaviors.d.ts.map +1 -0
- package/dist/adw/element-behaviors.js +299 -0
- package/dist/adw/element-behaviors.js.map +1 -0
- package/dist/adw/element-config.d.ts +9 -0
- package/dist/adw/element-config.d.ts.map +1 -0
- package/dist/adw/element-config.js +137 -0
- package/dist/adw/element-config.js.map +1 -0
- package/dist/adw/index.d.ts +4 -0
- package/dist/adw/index.d.ts.map +1 -0
- package/dist/adw/index.js +3 -0
- package/dist/adw/index.js.map +1 -0
- package/dist/adw/prop-types.d.ts +29 -0
- package/dist/adw/prop-types.d.ts.map +1 -0
- package/dist/adw/prop-types.js +2 -0
- package/dist/adw/prop-types.js.map +1 -0
- package/dist/bootstrap.d.ts +2 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +5 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/components/application.d.ts +2 -2
- package/dist/components/application.d.ts.map +1 -1
- package/dist/components/application.js +31 -18
- package/dist/components/application.js.map +1 -1
- package/dist/components/element.d.ts +6 -0
- package/dist/components/element.d.ts.map +1 -0
- package/dist/components/element.js +29 -0
- package/dist/components/element.js.map +1 -0
- package/dist/components/window.d.ts +2 -2
- package/dist/components/window.d.ts.map +1 -1
- package/dist/components/window.js +10 -11
- package/dist/components/window.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -0
- package/dist/element-behaviors.d.ts +2 -0
- package/dist/element-behaviors.d.ts.map +1 -0
- package/dist/element-behaviors.js +348 -0
- package/dist/element-behaviors.js.map +1 -0
- package/dist/element-config.d.ts +10 -0
- package/dist/element-config.d.ts.map +1 -0
- package/dist/element-config.js +146 -0
- package/dist/element-config.js.map +1 -0
- package/dist/hooks/use-application.d.ts +4 -3
- package/dist/hooks/use-application.d.ts.map +1 -1
- package/dist/hooks/use-application.js +5 -4
- package/dist/hooks/use-application.js.map +1 -1
- package/dist/hooks/use-bind-setting.d.ts +21 -4
- package/dist/hooks/use-bind-setting.d.ts.map +1 -1
- package/dist/hooks/use-bind-setting.js +27 -16
- package/dist/hooks/use-bind-setting.js.map +1 -1
- package/dist/hooks/use-merged-refs.d.ts +8 -0
- package/dist/hooks/use-merged-refs.d.ts.map +1 -0
- package/dist/hooks/use-merged-refs.js +48 -0
- package/dist/hooks/use-merged-refs.js.map +1 -0
- package/dist/hooks/use-object-value.d.ts +3 -2
- package/dist/hooks/use-object-value.d.ts.map +1 -1
- package/dist/hooks/use-object-value.js +18 -21
- package/dist/hooks/use-object-value.js.map +1 -1
- package/dist/hooks/use-parent-window.d.ts +3 -2
- package/dist/hooks/use-parent-window.d.ts.map +1 -1
- package/dist/hooks/use-parent-window.js +3 -2
- package/dist/hooks/use-parent-window.js.map +1 -1
- package/dist/hooks/use-property.d.ts +5 -5
- package/dist/hooks/use-property.d.ts.map +1 -1
- package/dist/hooks/use-property.js +4 -3
- package/dist/hooks/use-property.js.map +1 -1
- package/dist/hooks/use-setting.d.ts +5 -16
- package/dist/hooks/use-setting.d.ts.map +1 -1
- package/dist/hooks/use-setting.js +16 -11
- package/dist/hooks/use-setting.js.map +1 -1
- package/dist/hooks/use-signal.d.ts +10 -7
- package/dist/hooks/use-signal.d.ts.map +1 -1
- package/dist/hooks/use-signal.js +29 -18
- package/dist/hooks/use-signal.js.map +1 -1
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +6 -7
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +5 -7
- package/dist/internal.js.map +1 -1
- package/dist/prop-types.d.ts +110 -0
- package/dist/prop-types.d.ts.map +1 -0
- package/dist/prop-types.js +2 -0
- package/dist/prop-types.js.map +1 -0
- package/dist/reconciler/apply-props.d.ts +10 -7
- package/dist/reconciler/apply-props.d.ts.map +1 -1
- package/dist/reconciler/apply-props.js +182 -84
- package/dist/reconciler/apply-props.js.map +1 -1
- package/dist/reconciler/behaviors.d.ts +59 -0
- package/dist/reconciler/behaviors.d.ts.map +1 -0
- package/dist/reconciler/behaviors.js +172 -0
- package/dist/reconciler/behaviors.js.map +1 -0
- package/dist/reconciler/child-routing.d.ts +5 -0
- package/dist/reconciler/child-routing.d.ts.map +1 -0
- package/dist/reconciler/child-routing.js +156 -0
- package/dist/reconciler/child-routing.js.map +1 -0
- package/dist/reconciler/host-config.d.ts +8 -12
- package/dist/reconciler/host-config.d.ts.map +1 -1
- package/dist/reconciler/host-config.js +175 -270
- package/dist/reconciler/host-config.js.map +1 -1
- package/dist/reconciler/instance.d.ts +4 -5
- package/dist/reconciler/instance.d.ts.map +1 -1
- package/dist/reconciler/instance.js +44 -22
- package/dist/reconciler/instance.js.map +1 -1
- package/dist/reconciler/metadata.d.ts +17 -0
- package/dist/reconciler/metadata.d.ts.map +1 -0
- package/dist/reconciler/metadata.js +82 -0
- package/dist/reconciler/metadata.js.map +1 -0
- package/dist/reconciler/node.d.ts +76 -0
- package/dist/reconciler/node.d.ts.map +1 -0
- package/dist/reconciler/node.js +53 -0
- package/dist/reconciler/node.js.map +1 -0
- package/dist/reconciler/placement.d.ts +5 -0
- package/dist/reconciler/placement.d.ts.map +1 -0
- package/dist/reconciler/placement.js +175 -0
- package/dist/reconciler/placement.js.map +1 -0
- package/dist/reconciler/registry.d.ts +92 -0
- package/dist/reconciler/registry.d.ts.map +1 -0
- package/dist/reconciler/registry.js +64 -0
- package/dist/reconciler/registry.js.map +1 -0
- package/dist/reconciler/root-element.d.ts +9 -12
- package/dist/reconciler/root-element.d.ts.map +1 -1
- package/dist/reconciler/root-element.js +6 -6
- package/dist/reconciler/root-element.js.map +1 -1
- package/dist/reconciler/root.d.ts +56 -0
- package/dist/reconciler/root.d.ts.map +1 -0
- package/dist/reconciler/root.js +109 -0
- package/dist/reconciler/root.js.map +1 -0
- package/dist/reconciler/signals.d.ts +10 -0
- package/dist/reconciler/signals.d.ts.map +1 -0
- package/dist/reconciler/signals.js +70 -0
- package/dist/reconciler/signals.js.map +1 -0
- package/dist/reconciler/text.d.ts +19 -0
- package/dist/reconciler/text.d.ts.map +1 -0
- package/dist/reconciler/text.js +276 -0
- package/dist/reconciler/text.js.map +1 -0
- package/dist/utils/accessible-metadata.d.ts +11 -4
- package/dist/utils/accessible-metadata.d.ts.map +1 -1
- package/dist/utils/accessible-metadata.js +20 -17
- package/dist/utils/accessible-metadata.js.map +1 -1
- package/dist/{reconciler/accessible.d.ts → utils/accessible-props.d.ts} +7 -6
- package/dist/utils/accessible-props.d.ts.map +1 -0
- package/dist/utils/accessible-props.js +181 -0
- package/dist/utils/accessible-props.js.map +1 -0
- package/dist/utils/ref-prop.d.ts +15 -0
- package/dist/utils/ref-prop.d.ts.map +1 -0
- package/dist/utils/ref-prop.js +18 -0
- package/dist/utils/ref-prop.js.map +1 -0
- package/dist/utils/settings.d.ts +17 -0
- package/dist/utils/settings.d.ts.map +1 -0
- package/dist/utils/settings.js +37 -0
- package/dist/utils/settings.js.map +1 -0
- package/dist/utils/variant.d.ts +57 -0
- package/dist/utils/variant.d.ts.map +1 -0
- package/dist/utils/variant.js +197 -0
- package/dist/utils/variant.js.map +1 -0
- package/env.d.ts +9 -0
- package/package.json +36 -11
- package/src/adw/config.ts +1 -0
- package/src/adw/dialog.tsx +35 -0
- package/src/adw/element-behaviors.ts +379 -0
- package/src/adw/element-config.ts +140 -0
- package/src/adw/index.ts +4 -0
- package/src/adw/prop-types.ts +42 -0
- package/src/bootstrap.ts +5 -0
- package/src/components/application.tsx +42 -23
- package/src/components/element.tsx +47 -0
- package/src/components/window.tsx +12 -13
- package/src/config.ts +3 -0
- package/src/element-behaviors.ts +424 -0
- package/src/element-config.ts +148 -0
- package/src/env.d.ts +1 -0
- package/src/hooks/use-application.ts +6 -4
- package/src/hooks/use-bind-setting.ts +47 -31
- package/src/hooks/use-merged-refs.ts +64 -0
- package/src/hooks/use-object-value.ts +27 -23
- package/src/hooks/use-parent-window.ts +4 -2
- package/src/hooks/use-property.ts +11 -10
- package/src/hooks/use-setting.ts +20 -33
- package/src/hooks/use-signal.ts +37 -48
- package/src/index.ts +7 -8
- package/src/internal.ts +7 -18
- package/src/prop-types.ts +142 -0
- package/src/reconciler/apply-props.ts +233 -85
- package/src/reconciler/behaviors.ts +324 -0
- package/src/reconciler/child-routing.ts +202 -0
- package/src/reconciler/host-config.ts +239 -366
- package/src/reconciler/instance.ts +76 -24
- package/src/reconciler/metadata.ts +119 -0
- package/src/reconciler/node.ts +161 -0
- package/src/reconciler/placement.ts +255 -0
- package/src/reconciler/registry.ts +161 -0
- package/src/reconciler/root-element.ts +9 -11
- package/src/reconciler/root.ts +175 -0
- package/src/reconciler/signals.ts +113 -0
- package/src/reconciler/text.ts +407 -0
- package/src/utils/accessible-metadata.ts +23 -18
- package/src/utils/accessible-props.ts +279 -0
- package/src/utils/ref-prop.ts +30 -0
- package/src/utils/settings.ts +69 -0
- package/src/utils/variant.ts +368 -0
- package/dist/hooks/use-merge-refs.d.ts +0 -3
- package/dist/hooks/use-merge-refs.d.ts.map +0 -1
- package/dist/hooks/use-merge-refs.js +0 -48
- package/dist/hooks/use-merge-refs.js.map +0 -1
- package/dist/hooks/use-object-attachment.d.ts +0 -10
- package/dist/hooks/use-object-attachment.d.ts.map +0 -1
- package/dist/hooks/use-object-attachment.js +0 -24
- package/dist/hooks/use-object-attachment.js.map +0 -1
- package/dist/libraries/adw/dialog.d.ts.map +0 -1
- package/dist/libraries/adw/dialog.js +0 -25
- package/dist/libraries/adw/dialog.js.map +0 -1
- package/dist/libraries/adw/index.d.ts +0 -2
- package/dist/libraries/adw/index.d.ts.map +0 -1
- package/dist/libraries/adw/index.js +0 -2
- package/dist/libraries/adw/index.js.map +0 -1
- package/dist/reconciler/accessible.d.ts.map +0 -1
- package/dist/reconciler/accessible.js +0 -143
- package/dist/reconciler/accessible.js.map +0 -1
- package/dist/reconciler/commit-flush.d.ts +0 -3
- package/dist/reconciler/commit-flush.d.ts.map +0 -1
- package/dist/reconciler/commit-flush.js +0 -13
- package/dist/reconciler/commit-flush.js.map +0 -1
- package/dist/reconciler/container-attach.d.ts +0 -10
- package/dist/reconciler/container-attach.d.ts.map +0 -1
- package/dist/reconciler/container-attach.js +0 -216
- package/dist/reconciler/container-attach.js.map +0 -1
- package/dist/reconciler/content-rebuild.d.ts +0 -3
- package/dist/reconciler/content-rebuild.d.ts.map +0 -1
- package/dist/reconciler/content-rebuild.js +0 -15
- package/dist/reconciler/content-rebuild.js.map +0 -1
- package/dist/reconciler/dispatch.d.ts +0 -6
- package/dist/reconciler/dispatch.d.ts.map +0 -1
- package/dist/reconciler/dispatch.js +0 -61
- package/dist/reconciler/dispatch.js.map +0 -1
- package/dist/reconciler/element-prop-appliers.d.ts +0 -5
- package/dist/reconciler/element-prop-appliers.d.ts.map +0 -1
- package/dist/reconciler/element-prop-appliers.js +0 -104
- package/dist/reconciler/element-prop-appliers.js.map +0 -1
- package/dist/reconciler/element-props.d.ts +0 -25
- package/dist/reconciler/element-props.d.ts.map +0 -1
- package/dist/reconciler/element-props.js +0 -157
- package/dist/reconciler/element-props.js.map +0 -1
- package/dist/reconciler/label-text-rebuild.d.ts +0 -3
- package/dist/reconciler/label-text-rebuild.d.ts.map +0 -1
- package/dist/reconciler/label-text-rebuild.js +0 -22
- package/dist/reconciler/label-text-rebuild.js.map +0 -1
- package/dist/reconciler/portal.d.ts +0 -11
- package/dist/reconciler/portal.d.ts.map +0 -1
- package/dist/reconciler/portal.js +0 -20
- package/dist/reconciler/portal.js.map +0 -1
- package/dist/reconciler/reconciler-error-handler.d.ts +0 -7
- package/dist/reconciler/reconciler-error-handler.d.ts.map +0 -1
- package/dist/reconciler/reconciler-error-handler.js +0 -24
- package/dist/reconciler/reconciler-error-handler.js.map +0 -1
- package/dist/reconciler/reconciler-root.d.ts +0 -19
- package/dist/reconciler/reconciler-root.d.ts.map +0 -1
- package/dist/reconciler/reconciler-root.js +0 -24
- package/dist/reconciler/reconciler-root.js.map +0 -1
- package/dist/reconciler/reconciler.d.ts +0 -3
- package/dist/reconciler/reconciler.d.ts.map +0 -1
- package/dist/reconciler/reconciler.js +0 -12
- package/dist/reconciler/reconciler.js.map +0 -1
- package/dist/reconciler/render.d.ts +0 -23
- package/dist/reconciler/render.d.ts.map +0 -1
- package/dist/reconciler/render.js +0 -46
- package/dist/reconciler/render.js.map +0 -1
- package/dist/reconciler/signal-store.d.ts +0 -22
- package/dist/reconciler/signal-store.d.ts.map +0 -1
- package/dist/reconciler/signal-store.js +0 -84
- package/dist/reconciler/signal-store.js.map +0 -1
- package/dist/reconciler/state.d.ts +0 -36
- package/dist/reconciler/state.d.ts.map +0 -1
- package/dist/reconciler/state.js +0 -38
- package/dist/reconciler/state.js.map +0 -1
- package/dist/reconciler/text-buffer-controller.d.ts +0 -17
- package/dist/reconciler/text-buffer-controller.d.ts.map +0 -1
- package/dist/reconciler/text-buffer-controller.js +0 -102
- package/dist/reconciler/text-buffer-controller.js.map +0 -1
- package/dist/reconciler/text-buffer-rebuild.d.ts +0 -3
- package/dist/reconciler/text-buffer-rebuild.d.ts.map +0 -1
- package/dist/reconciler/text-buffer-rebuild.js +0 -7
- package/dist/reconciler/text-buffer-rebuild.js.map +0 -1
- package/dist/reconciler/text-node.d.ts +0 -7
- package/dist/reconciler/text-node.d.ts.map +0 -1
- package/dist/reconciler/text-node.js +0 -8
- package/dist/reconciler/text-node.js.map +0 -1
- package/dist/reconciler/types.d.ts +0 -5
- package/dist/reconciler/types.d.ts.map +0 -1
- package/dist/reconciler/types.js +0 -2
- package/dist/reconciler/types.js.map +0 -1
- package/dist/reconciler/visibility.d.ts +0 -6
- package/dist/reconciler/visibility.d.ts.map +0 -1
- package/dist/reconciler/visibility.js +0 -57
- package/dist/reconciler/visibility.js.map +0 -1
- package/dist/reconciler/wrapper-apply.d.ts +0 -6
- package/dist/reconciler/wrapper-apply.d.ts.map +0 -1
- package/dist/reconciler/wrapper-apply.js +0 -287
- package/dist/reconciler/wrapper-apply.js.map +0 -1
- package/dist/reconciler/wrapper-content.d.ts +0 -8
- package/dist/reconciler/wrapper-content.d.ts.map +0 -1
- package/dist/reconciler/wrapper-content.js +0 -19
- package/dist/reconciler/wrapper-content.js.map +0 -1
- package/dist/reconciler/wrapper-node.d.ts +0 -8
- package/dist/reconciler/wrapper-node.d.ts.map +0 -1
- package/dist/reconciler/wrapper-node.js +0 -4
- package/dist/reconciler/wrapper-node.js.map +0 -1
- package/dist/reconciler/wrapper-protocol.d.ts +0 -13
- package/dist/reconciler/wrapper-protocol.d.ts.map +0 -1
- package/dist/reconciler/wrapper-protocol.js +0 -20
- package/dist/reconciler/wrapper-protocol.js.map +0 -1
- package/dist/utils/create-element-component.d.ts +0 -4
- package/dist/utils/create-element-component.d.ts.map +0 -1
- package/dist/utils/create-element-component.js +0 -54
- package/dist/utils/create-element-component.js.map +0 -1
- package/dist/utils/gtype.d.ts +0 -16
- package/dist/utils/gtype.d.ts.map +0 -1
- package/dist/utils/gtype.js +0 -127
- package/dist/utils/gtype.js.map +0 -1
- package/dist/utils/notify-name.d.ts +0 -5
- package/dist/utils/notify-name.d.ts.map +0 -1
- package/dist/utils/notify-name.js +0 -6
- package/dist/utils/notify-name.js.map +0 -1
- package/dist/utils/object-prop.d.ts +0 -8
- package/dist/utils/object-prop.d.ts.map +0 -1
- package/dist/utils/object-prop.js +0 -9
- package/dist/utils/object-prop.js.map +0 -1
- package/dist/utils/settings-accessor.d.ts +0 -8
- package/dist/utils/settings-accessor.d.ts.map +0 -1
- package/dist/utils/settings-accessor.js +0 -69
- package/dist/utils/settings-accessor.js.map +0 -1
- package/dist/utils/wrapper-node-jsx.d.ts +0 -32
- package/dist/utils/wrapper-node-jsx.d.ts.map +0 -1
- package/dist/utils/wrapper-node-jsx.js +0 -2
- package/dist/utils/wrapper-node-jsx.js.map +0 -1
- package/src/hooks/use-merge-refs.ts +0 -53
- package/src/hooks/use-object-attachment.ts +0 -35
- package/src/libraries/adw/dialog.tsx +0 -34
- package/src/libraries/adw/index.ts +0 -1
- package/src/reconciler/accessible.ts +0 -232
- package/src/reconciler/commit-flush.ts +0 -13
- package/src/reconciler/container-attach.ts +0 -219
- package/src/reconciler/content-rebuild.ts +0 -19
- package/src/reconciler/dispatch.ts +0 -58
- package/src/reconciler/element-prop-appliers.ts +0 -110
- package/src/reconciler/element-props.ts +0 -192
- package/src/reconciler/label-text-rebuild.ts +0 -26
- package/src/reconciler/portal.ts +0 -28
- package/src/reconciler/reconciler-error-handler.ts +0 -29
- package/src/reconciler/reconciler-root.ts +0 -57
- package/src/reconciler/reconciler.ts +0 -13
- package/src/reconciler/render.ts +0 -61
- package/src/reconciler/signal-store.ts +0 -103
- package/src/reconciler/state.ts +0 -72
- package/src/reconciler/text-buffer-controller.ts +0 -107
- package/src/reconciler/text-buffer-rebuild.ts +0 -12
- package/src/reconciler/text-node.ts +0 -13
- package/src/reconciler/types.ts +0 -6
- package/src/reconciler/visibility.ts +0 -52
- package/src/reconciler/wrapper-apply.ts +0 -308
- package/src/reconciler/wrapper-content.ts +0 -24
- package/src/reconciler/wrapper-node.ts +0 -8
- package/src/reconciler/wrapper-protocol.ts +0 -32
- package/src/utils/create-element-component.ts +0 -77
- package/src/utils/gtype.ts +0 -166
- package/src/utils/notify-name.ts +0 -10
- package/src/utils/object-prop.ts +0 -13
- package/src/utils/settings-accessor.ts +0 -89
- package/src/utils/wrapper-node-jsx.ts +0 -34
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type * as GObject from "@gtkx/gi/gobject";
|
|
2
|
+
|
|
3
|
+
/** The props of a host element or node, as React passes them through the reconciler. */
|
|
4
|
+
type Props = Record<string, unknown>;
|
|
5
|
+
|
|
6
|
+
/** Per-child values a slot hook receives while placing or moving one child. */
|
|
7
|
+
type PlaceInfo = {
|
|
8
|
+
slot: string;
|
|
9
|
+
index: number;
|
|
10
|
+
sibling: GObject.Object | null;
|
|
11
|
+
adopted: GObject.Object | null;
|
|
12
|
+
props: Props;
|
|
13
|
+
context: unknown;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/** Per-child values a slot hook receives while removing one child. */
|
|
17
|
+
type DetachInfo = {
|
|
18
|
+
slot: string;
|
|
19
|
+
adopted: GObject.Object | null;
|
|
20
|
+
props: Props;
|
|
21
|
+
context: unknown;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Customizes how one element type places children and applies props. Every hook receives the
|
|
26
|
+
* GObject instance and a private per-node `context` built once by `createContext`. A slot hook
|
|
27
|
+
* claims a child by returning a non-`undefined` value; that value, or `resolve`, is the object
|
|
28
|
+
* the container adopts for the child. `update` returns the prop names it consumed so those props
|
|
29
|
+
* are not also set as plain GObject properties. `create` builds the GObject for types whose
|
|
30
|
+
* constructor does more than set properties, and is consulted for its own type only, never
|
|
31
|
+
* inherited by subtypes.
|
|
32
|
+
*/
|
|
33
|
+
type ElementBehavior<T extends GObject.Object = GObject.Object> = {
|
|
34
|
+
create?: (props: Props) => GObject.Object;
|
|
35
|
+
createContext?: (object: T) => unknown;
|
|
36
|
+
attach?: (object: T, child: GObject.Object, info: PlaceInfo) => unknown;
|
|
37
|
+
reorder?: (object: T, child: GObject.Object, info: PlaceInfo) => unknown;
|
|
38
|
+
detach?: (object: T, child: GObject.Object, info: DetachInfo) => void;
|
|
39
|
+
resolve?: (object: T, child: GObject.Object) => GObject.Object | null;
|
|
40
|
+
update?: (object: T, prev: Props, next: Props, context: unknown) => Iterable<string> | undefined;
|
|
41
|
+
flush?: (object: T, context: unknown) => void;
|
|
42
|
+
mount?: (object: T, context: unknown) => void;
|
|
43
|
+
unmount?: (object: T, context: unknown) => void;
|
|
44
|
+
deferred?: string[];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/** A named export in a module, referenced as plain data (the module is never imported at runtime). */
|
|
48
|
+
type ModuleExport = { module: string; export: string };
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Per-element configuration keyed by GLib type name: whether the element is lazy (its GObject is
|
|
52
|
+
* created by its parent container, as pages and layout children are), the custom behaviors bound to
|
|
53
|
+
* its type, an optional component that wraps the generated element, and the base props interface its
|
|
54
|
+
* generated props extend. `component` and `props` are inert at runtime; they are read only by codegen.
|
|
55
|
+
*/
|
|
56
|
+
type ElementConfig<T extends GObject.Object = GObject.Object> = {
|
|
57
|
+
lazy?: boolean;
|
|
58
|
+
behaviors?: ElementBehavior<T>[];
|
|
59
|
+
component?: ModuleExport;
|
|
60
|
+
props?: ModuleExport;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Every registered element config, keyed by GLib type name. Adwaita entries appear once `@gtkx/react/adw`
|
|
65
|
+
* is loaded.
|
|
66
|
+
*/
|
|
67
|
+
const ELEMENTS: Record<string, ElementConfig> = {};
|
|
68
|
+
|
|
69
|
+
/** Props a behavior applies after construction; the constructor is never given them. */
|
|
70
|
+
const deferredProps = (behavior: ElementBehavior): string[] => behavior.deferred ?? [];
|
|
71
|
+
|
|
72
|
+
const mergeBehaviors = (base: ElementConfig, added: ElementBehavior[], isPrepended: boolean): ElementBehavior[] => {
|
|
73
|
+
const baseBehaviors = base.behaviors ?? [];
|
|
74
|
+
|
|
75
|
+
return isPrepended ? [...added, ...baseBehaviors] : [...baseBehaviors, ...added];
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const mergeConfigEntry = (base: ElementConfig, added: ElementConfig<never>, isPrepended = false): ElementConfig => {
|
|
79
|
+
const entry: ElementConfig = { ...base };
|
|
80
|
+
|
|
81
|
+
if (added.behaviors !== undefined) {
|
|
82
|
+
entry.behaviors = mergeBehaviors(entry, added.behaviors as ElementBehavior[], isPrepended);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (added.lazy === true) {
|
|
86
|
+
entry.lazy = true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (added.component !== undefined) {
|
|
90
|
+
entry.component = added.component;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (added.props !== undefined) {
|
|
94
|
+
entry.props = added.props;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return entry;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Merges maps of {@link ElementConfig} keyed by GLib type name into one, concatenating each type's
|
|
102
|
+
* behaviors in the order the maps are given (an earlier map's behaviors come first) and taking the last
|
|
103
|
+
* lazy flag, component, and props seen. Use it to combine an app's element config with its behaviors.
|
|
104
|
+
*/
|
|
105
|
+
const mergeElementConfigs = (...maps: Record<string, ElementConfig<never>>[]): Record<string, ElementConfig> => {
|
|
106
|
+
const merged: Record<string, ElementConfig> = {};
|
|
107
|
+
|
|
108
|
+
for (const map of maps) {
|
|
109
|
+
for (const [type, config] of Object.entries(map)) {
|
|
110
|
+
merged[type] = mergeConfigEntry(merged[type] ?? {}, config);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return merged;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Registers a map of {@link ElementConfig} keyed by GLib type name, merging each entry into the
|
|
119
|
+
* registry. Behaviors are appended by default (the framework's built-ins register this way); pass
|
|
120
|
+
* `{ prepend: true }` for an app's own configuration so its behaviors are consulted before the
|
|
121
|
+
* built-ins for the same slot, letting it override them regardless of registration order.
|
|
122
|
+
*/
|
|
123
|
+
const registerElements = (
|
|
124
|
+
map: Record<string, ElementConfig<never>>,
|
|
125
|
+
options: { prepend?: boolean } = {},
|
|
126
|
+
): void => {
|
|
127
|
+
for (const [type, config] of Object.entries(map)) {
|
|
128
|
+
ELEMENTS[type] = mergeConfigEntry(ELEMENTS[type] ?? {}, config, options.prepend === true);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Identity helper that types the module named by the `elements` entry of `gtkx.config.ts`, enabling
|
|
134
|
+
* editor autocompletion and type checking. Key each entry by GLib type name and annotate each hook's
|
|
135
|
+
* object parameter with the concrete GObject class the behavior applies to.
|
|
136
|
+
*/
|
|
137
|
+
const defineElements = (elements: Record<string, ElementConfig<never>>): Record<string, ElementConfig<never>> =>
|
|
138
|
+
elements;
|
|
139
|
+
|
|
140
|
+
/** Spreads one config across many GLib type names. */
|
|
141
|
+
const forTypes = (types: string[], config: ElementConfig<never>): Record<string, ElementConfig<never>> =>
|
|
142
|
+
Object.fromEntries(types.map((type) => [type, config]));
|
|
143
|
+
|
|
144
|
+
/** References a base props interface exported from `@gtkx/react/internal`. */
|
|
145
|
+
const internal = (name: string): ModuleExport => ({ module: "@gtkx/react/internal", export: name });
|
|
146
|
+
|
|
147
|
+
export {
|
|
148
|
+
ELEMENTS,
|
|
149
|
+
deferredProps,
|
|
150
|
+
mergeElementConfigs,
|
|
151
|
+
registerElements,
|
|
152
|
+
defineElements,
|
|
153
|
+
forTypes,
|
|
154
|
+
internal,
|
|
155
|
+
type Props,
|
|
156
|
+
type PlaceInfo,
|
|
157
|
+
type DetachInfo,
|
|
158
|
+
type ElementBehavior,
|
|
159
|
+
type ModuleExport,
|
|
160
|
+
type ElementConfig,
|
|
161
|
+
};
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/** The type of the shared {@link rootElement} marker used as a default top-level container. */
|
|
2
|
+
type RootElement = { [ROOT_ELEMENT_BRAND]: true };
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export type RootElement = { [ROOT_ELEMENT]: true };
|
|
4
|
+
const ROOT_ELEMENT_BRAND: unique symbol = Symbol.for("gtkx:root-element");
|
|
5
|
+
/** A shared marker value used as the default top-level container for rendering and portals. */
|
|
6
|
+
const rootElement: RootElement = { [ROOT_ELEMENT_BRAND]: true };
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export const rootElement: RootElement = { [ROOT_ELEMENT]: true };
|
|
8
|
+
/** Reports whether an arbitrary value is a {@link rootElement} marker. */
|
|
9
|
+
const isRootElement = (value: unknown): value is RootElement =>
|
|
10
|
+
typeof value === "object" && value !== null && Object.hasOwn(value, ROOT_ELEMENT_BRAND);
|
|
12
11
|
|
|
13
|
-
export
|
|
14
|
-
typeof value === "object" && value !== null && ROOT_ELEMENT in value;
|
|
12
|
+
export { rootElement, isRootElement, type RootElement };
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import type { ErrorInfo, ReactNode } from "react";
|
|
2
|
+
import * as Gdk from "@gtkx/gi/gdk";
|
|
3
|
+
import { createLogger, type Logger } from "@gtkx/utils";
|
|
4
|
+
import { ConcurrentRoot } from "react-reconciler/constants.js";
|
|
5
|
+
import { type Container, reconciler } from "./host-config.js";
|
|
6
|
+
import { rootElement } from "./root-element.js";
|
|
7
|
+
import { endSuppressionNow } from "./signals.js";
|
|
8
|
+
|
|
9
|
+
type OpaqueRoot = { [opaqueRoot]: true };
|
|
10
|
+
|
|
11
|
+
type RootErrorCallbacks = {
|
|
12
|
+
onUncaughtError?: (error: unknown, info: ErrorInfo) => void;
|
|
13
|
+
onCaughtError?: (error: unknown, info: ErrorInfo) => void;
|
|
14
|
+
onRecoverableError?: (error: unknown, info: ErrorInfo) => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type ReconcilerRootOptions = RootErrorCallbacks & { containerInfo: Container };
|
|
18
|
+
|
|
19
|
+
/** A root that mounts an element tree into an explicit container and reports render errors. */
|
|
20
|
+
type ReconcilerRoot = {
|
|
21
|
+
update: (element: ReactNode) => void;
|
|
22
|
+
unmount: (teardown: (root: ReconcilerRoot) => Promise<void>) => Promise<void>;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** The object {@link createRoot} returns: it renders an element tree into a container and can tear it down. */
|
|
26
|
+
type Root = {
|
|
27
|
+
render: (element: ReactNode) => void;
|
|
28
|
+
unmount: () => void;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type ErrorHandler = (error: unknown) => void;
|
|
32
|
+
type ErrorHandlerSlot = { get: () => ErrorHandler | null; set: (handler: ErrorHandler) => ErrorHandler | null };
|
|
33
|
+
|
|
34
|
+
declare const opaqueRoot: unique symbol;
|
|
35
|
+
const log: Logger = createLogger("react");
|
|
36
|
+
const activeRoots: Set<OpaqueRoot> = new Set();
|
|
37
|
+
const errorHandlerSlot = createErrorHandlerSlot();
|
|
38
|
+
|
|
39
|
+
function createErrorHandlerSlot(): ErrorHandlerSlot {
|
|
40
|
+
let current: ErrorHandler | null = null;
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
get: () => current,
|
|
44
|
+
set: (handler) => {
|
|
45
|
+
const previous = current;
|
|
46
|
+
current = handler;
|
|
47
|
+
|
|
48
|
+
return previous;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Installs a process-wide handler for errors thrown while rendering or applying an update.
|
|
55
|
+
*
|
|
56
|
+
* @param handler The handler to install.
|
|
57
|
+
* @returns The previously installed handler, or null.
|
|
58
|
+
*/
|
|
59
|
+
const setReconcilerErrorHandler = (handler: ErrorHandler): ErrorHandler | null => errorHandlerSlot.set(handler);
|
|
60
|
+
|
|
61
|
+
const rethrowUncaughtRenderError = (error: unknown): never => {
|
|
62
|
+
endSuppressionNow();
|
|
63
|
+
throw error;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const logCaughtRenderError = (error: unknown): void => {
|
|
67
|
+
endSuppressionNow();
|
|
68
|
+
log.error("caught render error", error);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const openContainer = (containerInfo: Container, callbacks: RootErrorCallbacks): OpaqueRoot => {
|
|
72
|
+
const container = reconciler.createContainer(
|
|
73
|
+
containerInfo,
|
|
74
|
+
ConcurrentRoot,
|
|
75
|
+
null,
|
|
76
|
+
false,
|
|
77
|
+
null,
|
|
78
|
+
"",
|
|
79
|
+
(error, info) => {
|
|
80
|
+
errorHandlerSlot.get()?.(error);
|
|
81
|
+
callbacks.onUncaughtError?.(error, info);
|
|
82
|
+
},
|
|
83
|
+
(error, info) => {
|
|
84
|
+
errorHandlerSlot.get()?.(error);
|
|
85
|
+
callbacks.onCaughtError?.(error, info);
|
|
86
|
+
},
|
|
87
|
+
(error, info) => {
|
|
88
|
+
callbacks.onRecoverableError?.(error, info);
|
|
89
|
+
},
|
|
90
|
+
(): void => undefined,
|
|
91
|
+
) as OpaqueRoot;
|
|
92
|
+
|
|
93
|
+
activeRoots.add(container);
|
|
94
|
+
|
|
95
|
+
return container;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const unmountContainer = (container: OpaqueRoot): void => {
|
|
99
|
+
reconciler.updateContainer(null, container, null, null);
|
|
100
|
+
activeRoots.delete(container);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Creates a root that mounts an element tree into a container, routing render errors to the supplied callbacks.
|
|
105
|
+
*
|
|
106
|
+
* @param options The container to render into and the error callbacks to route failures to.
|
|
107
|
+
* @returns A {@link ReconcilerRoot}.
|
|
108
|
+
*/
|
|
109
|
+
const createReconcilerRoot = (options: ReconcilerRootOptions): ReconcilerRoot => {
|
|
110
|
+
const container = openContainer(options.containerInfo, options);
|
|
111
|
+
|
|
112
|
+
const root: ReconcilerRoot = {
|
|
113
|
+
update: (element) => {
|
|
114
|
+
reconciler.updateContainer(element, container, null, null);
|
|
115
|
+
},
|
|
116
|
+
unmount: async (teardown) => {
|
|
117
|
+
await teardown(root);
|
|
118
|
+
activeRoots.delete(container);
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
return root;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Creates a render root for a GTKX application.
|
|
127
|
+
*
|
|
128
|
+
* @param container The top-level container to render into; defaults to the shared {@link rootElement}.
|
|
129
|
+
* @returns A {@link Root} exposing render and unmount.
|
|
130
|
+
*/
|
|
131
|
+
const createRoot = (container: Container = rootElement): Root => {
|
|
132
|
+
const opaque = openContainer(container, {
|
|
133
|
+
onUncaughtError: rethrowUncaughtRenderError,
|
|
134
|
+
onCaughtError: logCaughtRenderError,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
render: (element) => {
|
|
139
|
+
reconciler.updateContainer(element, opaque, null, null);
|
|
140
|
+
},
|
|
141
|
+
unmount: () => {
|
|
142
|
+
unmountContainer(opaque);
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/** Unmounts every active render root and stops the originating signal from propagating further. */
|
|
148
|
+
const quit = (): typeof Gdk.EVENT_STOP => {
|
|
149
|
+
for (const container of activeRoots) {
|
|
150
|
+
unmountContainer(container);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return Gdk.EVENT_STOP;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Renders children into a container other than the surrounding tree.
|
|
158
|
+
*
|
|
159
|
+
* @param children The element tree to render.
|
|
160
|
+
* @param container The GObject, application, or {@link rootElement} to render into.
|
|
161
|
+
* @param key An optional stable key.
|
|
162
|
+
* @returns A React portal.
|
|
163
|
+
*/
|
|
164
|
+
const createPortal = (children: ReactNode, container: Container, key?: string): ReactNode =>
|
|
165
|
+
Object.assign(reconciler.createPortal(children, container, null, key ?? null), { type: "gtkx-portal", props: {} });
|
|
166
|
+
|
|
167
|
+
export {
|
|
168
|
+
setReconcilerErrorHandler,
|
|
169
|
+
createReconcilerRoot,
|
|
170
|
+
createRoot,
|
|
171
|
+
quit,
|
|
172
|
+
createPortal,
|
|
173
|
+
type ReconcilerRoot,
|
|
174
|
+
type Root,
|
|
175
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { getSignalBaseName, type SignalHandler } from "@gtkx/runtime";
|
|
2
|
+
import { camelCase } from "@gtkx/utils";
|
|
3
|
+
import type { HandlerRecord, SignalTarget } from "./node.js";
|
|
4
|
+
import { type TypeInfo, typeInfoFor } from "./metadata.js";
|
|
5
|
+
|
|
6
|
+
type SuppressionCounter = {
|
|
7
|
+
beginSuppression: () => void;
|
|
8
|
+
endSuppression: () => void;
|
|
9
|
+
endSuppressionNow: () => void;
|
|
10
|
+
isSuppressed: () => boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const NOTIFY_DETAIL_PREFIX = "notify::";
|
|
14
|
+
const suppressionCounter: SuppressionCounter = createSuppressionCounter();
|
|
15
|
+
const beginSuppression: () => void = suppressionCounter.beginSuppression;
|
|
16
|
+
const endSuppression: () => void = suppressionCounter.endSuppression;
|
|
17
|
+
const endSuppressionNow: () => void = suppressionCounter.endSuppressionNow;
|
|
18
|
+
const isSuppressed: () => boolean = suppressionCounter.isSuppressed;
|
|
19
|
+
|
|
20
|
+
function createSuppressionCounter(): SuppressionCounter {
|
|
21
|
+
let depth = 0;
|
|
22
|
+
|
|
23
|
+
const release = (): void => {
|
|
24
|
+
if (depth > 0) {
|
|
25
|
+
depth -= 1;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
beginSuppression: () => {
|
|
31
|
+
depth += 1;
|
|
32
|
+
},
|
|
33
|
+
endSuppression: () => {
|
|
34
|
+
queueMicrotask(release);
|
|
35
|
+
},
|
|
36
|
+
endSuppressionNow: release,
|
|
37
|
+
isSuppressed: () => depth > 0,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const getNotifyProperty = (signal: string): string | null =>
|
|
42
|
+
signal.startsWith(NOTIFY_DETAIL_PREFIX) ? camelCase(signal.slice(NOTIFY_DETAIL_PREFIX.length)) : null;
|
|
43
|
+
|
|
44
|
+
const isBlockableSignal = (info: TypeInfo, signal: string): boolean =>
|
|
45
|
+
info.userEventSignals.has(getSignalBaseName(signal));
|
|
46
|
+
|
|
47
|
+
const invokeHandler = (
|
|
48
|
+
target: SignalTarget,
|
|
49
|
+
record: HandlerRecord,
|
|
50
|
+
notifyProperty: string | null,
|
|
51
|
+
args: unknown[],
|
|
52
|
+
): unknown =>
|
|
53
|
+
notifyProperty === null
|
|
54
|
+
? record.handler(...args, target.object)
|
|
55
|
+
: record.handler(Reflect.get(target.object, notifyProperty), target.object);
|
|
56
|
+
|
|
57
|
+
const wrapHandler = (target: SignalTarget, record: HandlerRecord, notifyProperty: string | null): SignalHandler =>
|
|
58
|
+
(...args: unknown[]): unknown => {
|
|
59
|
+
if (record.blockable && isSuppressed()) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return target.dispatch(() => invokeHandler(target, record, notifyProperty, args));
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const connectHandler = (target: SignalTarget, prop: string, signal: string, handler: SignalHandler): void => {
|
|
67
|
+
const existing = target.handlers.get(prop);
|
|
68
|
+
|
|
69
|
+
if (existing?.signal === signal) {
|
|
70
|
+
existing.handler = handler;
|
|
71
|
+
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (existing !== undefined) {
|
|
76
|
+
target.object.off(existing.signal, existing.wrapped);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const isBlockable = isBlockableSignal(typeInfoFor(target.typeName), signal);
|
|
80
|
+
const notifyProperty = getNotifyProperty(signal);
|
|
81
|
+
const record: HandlerRecord = { signal, handler, wrapped: (): undefined => undefined, blockable: isBlockable };
|
|
82
|
+
record.wrapped = wrapHandler(target, record, notifyProperty);
|
|
83
|
+
target.object.on(signal, record.wrapped);
|
|
84
|
+
target.handlers.set(prop, record);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const disconnectHandler = (target: SignalTarget, prop: string): void => {
|
|
88
|
+
const record = target.handlers.get(prop);
|
|
89
|
+
|
|
90
|
+
if (record === undefined) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
target.object.off(record.signal, record.wrapped);
|
|
95
|
+
target.handlers.delete(prop);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const disconnectAllHandlers = (target: SignalTarget): void => {
|
|
99
|
+
for (const record of target.handlers.values()) {
|
|
100
|
+
target.object.off(record.signal, record.wrapped);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
target.handlers.clear();
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export {
|
|
107
|
+
beginSuppression,
|
|
108
|
+
endSuppression,
|
|
109
|
+
endSuppressionNow,
|
|
110
|
+
connectHandler,
|
|
111
|
+
disconnectHandler,
|
|
112
|
+
disconnectAllHandlers,
|
|
113
|
+
};
|