@peachy/react 0.0.11 → 0.0.13

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
@@ -23,7 +23,7 @@ Then setup your config file
23
23
  ```json
24
24
  // tsconfig.json
25
25
  {
26
- "extends": "@peachy/react/tsconfig",
26
+ "extends": "@peachy/react/tsconfig.lib",
27
27
  "include": ["@peachy/types"]
28
28
  }
29
29
  ```
package/dist/env.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/extra.d.mts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { PeachyExtraMethods } from "./types.mjs";
2
+ import GObject from "gi://GObject?version=2.0";
3
+ import Gtk from "gi://Gtk?version=4.0";
2
4
 
3
5
  //#region src/extra.d.ts
4
- declare const extraMap: Map<GObject.GType, PeachyExtraMethods<Gtk.Widget, {}>>;
6
+ declare const extraMap: Map<GObject.GType<unknown>, PeachyExtraMethods<Gtk.Widget, {}>>;
5
7
  //#endregion
6
8
  export { extraMap };
package/dist/extra.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import { getMetadata } from "./utilities/metadata.mjs";
2
2
  import Gtk from "gi://Gtk?version=4.0";
3
-
4
3
  //#region src/extra.ts
5
4
  /**
6
5
  * GTK has some limitations, so here we try to solve some of them
@@ -97,6 +96,5 @@ const extraMap = new Map([
97
96
  }
98
97
  }]
99
98
  ]);
100
-
101
99
  //#endregion
102
- export { extraMap };
100
+ export { extraMap };
package/dist/global.d.mts CHANGED
@@ -8,10 +8,13 @@ type SignalProps<Self extends GObject.Object> = { [S in keyof Self["$signals"] a
8
8
  declare global {
9
9
  namespace JSX {
10
10
  interface IntrinsicAttributes {
11
- childType?: string;
11
+ // react props
12
12
  ref?: Ref<any>;
13
13
  key?: Key | null | undefined;
14
- children?: OrArray<any>;
14
+ children?: OrArray<any>; // peachy props
15
+ /** @deprecated use `$type` instead */
16
+ childType?: string;
17
+ $type?: string;
15
18
  }
16
19
  type LibraryManagedAttributes<C, Props> = C["prototype"] extends GObject.Object ? Props & SignalProps<C["prototype"]> : Props;
17
20
  }
@@ -2,10 +2,11 @@ import { setMetadataFromProps } from "./utilities/metadata.mjs";
2
2
  import { typeMap } from "./type-map.mjs";
3
3
  import { appendChild, insertBefore, removeChild } from "./utilities/children.mjs";
4
4
  import { getEventListeners, getEventName, getProperties, updateWidget } from "./utilities/diff.mjs";
5
+ import { hideInstance, unhideInstance } from "./utilities/suspend.mjs";
5
6
  import Gtk from "gi://Gtk?version=4.0";
7
+ import { createContext } from "react";
6
8
  import GLib from "gi://GLib?version=2.0";
7
- import { DefaultEventPriority, NoEventPriority } from "react-reconciler/constants";
8
-
9
+ import { DefaultEventPriority, NoEventPriority } from "react-reconciler/constants.js";
9
10
  //#region src/hostconfig.ts
10
11
  const emptyObject = {};
11
12
  let updatePriority = NoEventPriority;
@@ -46,6 +47,7 @@ const hostConfig = {
46
47
  shouldSetTextContent() {
47
48
  return false;
48
49
  },
50
+ isPrimaryRenderer: true,
49
51
  supportsMutation: true,
50
52
  supportsHydration: false,
51
53
  supportsPersistence: false,
@@ -57,10 +59,7 @@ const hostConfig = {
57
59
  });
58
60
  },
59
61
  scheduleMicrotask: (fn) => {
60
- GLib.idle_add(GLib.PRIORITY_HIGH_IDLE, () => {
61
- fn();
62
- return GLib.SOURCE_REMOVE;
63
- });
62
+ Promise.resolve().then(fn);
64
63
  },
65
64
  removeChild(parentInstance, child) {
66
65
  removeChild(parentInstance, child);
@@ -81,7 +80,9 @@ const hostConfig = {
81
80
  appendChildToContainer(container, child) {
82
81
  appendChild(container, child);
83
82
  },
84
- detachDeletedInstance() {},
83
+ detachDeletedInstance(node) {
84
+ node.unparent();
85
+ },
85
86
  commitUpdate(widget, type, oldProps, newProps) {
86
87
  updateWidget(widget, oldProps, newProps);
87
88
  },
@@ -104,8 +105,34 @@ const hostConfig = {
104
105
  resolveEventType() {
105
106
  return null;
106
107
  },
107
- trackSchedulerEvent() {}
108
+ trackSchedulerEvent() {},
109
+ hideInstance(instance) {
110
+ hideInstance(instance);
111
+ },
112
+ hideTextInstance(textInstance) {
113
+ hideInstance(textInstance);
114
+ },
115
+ unhideInstance(instance) {
116
+ unhideInstance(instance);
117
+ },
118
+ unhideTextInstance(textInstance) {
119
+ unhideInstance(textInstance);
120
+ },
121
+ maySuspendCommit: () => false,
122
+ preloadInstance: () => true,
123
+ startSuspendingCommit: () => {},
124
+ suspendInstance: () => {},
125
+ waitForCommitToBeReady: () => null,
126
+ NotPendingTransition: null,
127
+ HostTransitionContext: createContext(null),
128
+ getInstanceFromNode() {
129
+ return null;
130
+ },
131
+ getParentSuspenseInstance() {
132
+ return null;
133
+ },
134
+ preparePortalMount() {},
135
+ noTimeout: -1
108
136
  };
109
-
110
137
  //#endregion
111
- export { hostConfig };
138
+ export { hostConfig };
package/dist/index.d.mts CHANGED
@@ -1,8 +1,20 @@
1
- import "./global.mjs";
2
1
  import Gtk from "gi://Gtk?version=4.0";
3
- import "reflect-metadata";
4
-
2
+ import { ReactNode, ReactPortal } from "react";
5
3
  //#region src/index.d.ts
6
- declare const render: (jsx: React.ReactNode, root: Gtk.Widget, callback?: () => void) => void;
4
+ /**
5
+ * @deprecated please use `createRoot` instead
6
+ */
7
+ declare const render: (jsx: ReactNode, root: Gtk.Widget, callback?: () => void) => void;
8
+ interface Root {
9
+ render(element: ReactNode): void;
10
+ unmount(): void;
11
+ }
12
+ declare function createRoot(container: Gtk.Widget, options?: {
13
+ identifierPrefix?: string;
14
+ onUncaughtError?: (e: Error) => void;
15
+ onCaughtError?: (e: Error) => void;
16
+ onRecoverableError?: (e: Error) => void;
17
+ }): Root;
18
+ declare function createPortal(children: ReactNode, container: Gtk.Widget, key?: string): ReactPortal;
7
19
  //#endregion
8
- export { render };
20
+ export { Root, createPortal, createRoot, render };
package/dist/index.mjs CHANGED
@@ -1,19 +1,39 @@
1
1
  import "./global.d.mts";
2
2
  import { hostConfig } from "./hostconfig.mjs";
3
+ import Gtk from "gi://Gtk?version=4.0";
4
+ import { ConcurrentRoot, LegacyRoot } from "react-reconciler/constants.js";
3
5
  import "reflect-metadata";
6
+ import "@peachy/polyfills/performance";
4
7
  import Reconciler from "react-reconciler";
5
-
6
8
  //#region src/index.ts
7
9
  const reconciler = Reconciler(hostConfig);
10
+ /**
11
+ * @deprecated please use `createRoot` instead
12
+ */
8
13
  const render = (jsx, root, callback) => {
9
- const container = reconciler.createContainer(root, 0, null, false, null, "peachy", console.error, console.error, console.error, () => {});
14
+ const container = reconciler.createContainer(root, LegacyRoot, null, false, null, "peachy", console.error, console.error, console.error, () => {});
10
15
  reconciler.updateContainer(jsx, container, null, callback);
11
16
  };
17
+ function createRoot(container, options) {
18
+ if (container instanceof Gtk.Widget === false) throw new Error("container must be a Gtk.Widget");
19
+ const fiberRoot = reconciler.createContainer(container, ConcurrentRoot, null, false, null, options?.identifierPrefix ?? "", options?.onUncaughtError ?? console.error, options?.onCaughtError ?? console.error, options?.onRecoverableError ?? console.error, console.error);
20
+ return {
21
+ render(element) {
22
+ reconciler.updateContainer(element, fiberRoot, null, null);
23
+ },
24
+ unmount() {
25
+ reconciler.updateContainer(null, fiberRoot, null, null);
26
+ reconciler.flushSyncWork();
27
+ }
28
+ };
29
+ }
30
+ function createPortal(children, container, key) {
31
+ return reconciler.createPortal(children, container, null, key);
32
+ }
12
33
  reconciler.injectIntoDevTools({
13
34
  bundleType: process.env.NODE_ENV === "development" ? 1 : 0,
14
35
  version: "0.0.1",
15
36
  rendererPackageName: "peachy"
16
37
  });
17
-
18
38
  //#endregion
19
- export { render };
39
+ export { createPortal, createRoot, render };
@@ -1,11 +1,9 @@
1
1
  import { transformType } from "./jsx-utils.mjs";
2
2
  import * as React from "react/jsx-dev-runtime";
3
-
4
3
  //#region src/jsx-dev-runtime.ts
5
4
  const jsxDEV = (type, ...args) => {
6
5
  const transformedType = transformType(type);
7
6
  return React.jsxDEV(transformedType, ...args);
8
7
  };
9
-
10
8
  //#endregion
11
- export { jsxDEV };
9
+ export { jsxDEV };
@@ -1,9 +1,8 @@
1
- import * as react from "react";
2
1
  import * as React from "react/jsx-runtime";
3
2
 
4
3
  //#region src/jsx-runtime.d.ts
5
4
  declare const jsx: typeof React.jsx;
6
5
  declare const jsxs: typeof React.jsxs;
7
- declare const Fragment: react.ExoticComponent<react.FragmentProps>;
6
+ declare const Fragment: typeof React.Fragment;
8
7
  //#endregion
9
8
  export { Fragment, jsx, jsxs };
@@ -1,6 +1,5 @@
1
1
  import { transformType } from "./jsx-utils.mjs";
2
2
  import * as React from "react/jsx-runtime";
3
-
4
3
  //#region src/jsx-runtime.ts
5
4
  const jsx = (type, ...args) => {
6
5
  const transformedType = transformType(type);
@@ -11,6 +10,5 @@ const jsxs = (type, ...args) => {
11
10
  return React.jsxs(transformedType, ...args);
12
11
  };
13
12
  const Fragment = React.Fragment;
14
-
15
13
  //#endregion
16
- export { Fragment, jsx, jsxs };
14
+ export { Fragment, jsx, jsxs };
@@ -1,6 +1,5 @@
1
1
  import { typeMap } from "./type-map.mjs";
2
2
  import GObject from "gi://GObject?version=2.0";
3
-
4
3
  //#region src/jsx-utils.ts
5
4
  function isGtkWidgetClass(type) {
6
5
  return typeof type === "function" && type.prototype instanceof GObject.Object;
@@ -13,6 +12,5 @@ const transformType = (type) => {
13
12
  }
14
13
  return type;
15
14
  };
16
-
17
15
  //#endregion
18
- export { transformType };
16
+ export { transformType };
@@ -1,4 +1,6 @@
1
+ import GObject from "gi://GObject?version=2.0";
2
+
1
3
  //#region src/type-map.d.ts
2
- declare const typeMap: Map<string, any>;
4
+ declare const typeMap: Map<string, GObject.ObjectClass>;
3
5
  //#endregion
4
6
  export { typeMap };
package/dist/type-map.mjs CHANGED
@@ -1,5 +1,4 @@
1
1
  //#region src/type-map.ts
2
2
  const typeMap = /* @__PURE__ */ new Map();
3
-
4
3
  //#endregion
5
- export { typeMap };
4
+ export { typeMap };
package/dist/types.d.mts CHANGED
@@ -1,10 +1,15 @@
1
1
  import GObject from "gi://GObject?version=2.0";
2
+ import Gtk from "gi://Gtk?version=4.0";
2
3
 
3
4
  //#region src/types.d.ts
4
5
  type Props = Record<string, unknown>;
5
6
  type Listener = (...args: any[]) => any;
6
7
  interface ReactionMetadata {
7
8
  childType?: string;
9
+ suspenseState?: {
10
+ parent: Gtk.Widget;
11
+ nextSibling: Gtk.Widget | null;
12
+ };
8
13
  }
9
14
  interface PeachyExtraMethods<T extends Gtk.Widget, State = {}> {
10
15
  appendChild?(parentInstance: T, child: GObject.Object): void;
@@ -1,5 +1,4 @@
1
1
  import { getExtraMethod } from "./extra.mjs";
2
-
3
2
  //#region src/utilities/children.ts
4
3
  function appendChild(parentInstance, child) {
5
4
  getExtraMethod(parentInstance, "appendChild")?.(parentInstance, child);
@@ -26,6 +25,5 @@ function getAllChildren(parentInstance) {
26
25
  }
27
26
  return children;
28
27
  }
29
-
30
28
  //#endregion
31
- export { appendChild, insertBefore, removeChild };
29
+ export { appendChild, insertBefore, removeChild };
@@ -1,9 +1,9 @@
1
1
  import { setMetadataFromProps } from "./metadata.mjs";
2
2
  import GObject from "gi://GObject?version=2.0";
3
-
4
3
  //#region src/utilities/diff.ts
5
4
  const INTERNAL_PROP_NAMES = new Set([
6
5
  "childType",
6
+ "$type",
7
7
  "ref",
8
8
  "key",
9
9
  "children"
@@ -39,6 +39,5 @@ function getEventListeners(props) {
39
39
  const getEventName = (event) => event.substring(2).replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "").replace(/:-?/, "::");
40
40
  const isEvent = (key) => key.startsWith("on");
41
41
  const isProperty = (key) => !isEvent(key) && !INTERNAL_PROP_NAMES.has(key);
42
-
43
42
  //#endregion
44
- export { getEventListeners, getEventName, getProperties, updateWidget };
43
+ export { getEventListeners, getEventName, getProperties, updateWidget };
@@ -1,7 +1,6 @@
1
1
  import { extraMap } from "../extra.mjs";
2
2
  import { getGtype } from "./type.mjs";
3
3
  import GObject from "gi://GObject?version=2.0";
4
-
5
4
  //#region src/utilities/extra.ts
6
5
  function getExtraMethod(object, method) {
7
6
  const gtype = getGtype(object);
@@ -11,6 +10,5 @@ function getExtraMethod(object, method) {
11
10
  }
12
11
  return null;
13
12
  }
14
-
15
13
  //#endregion
16
- export { getExtraMethod };
14
+ export { getExtraMethod };
@@ -1,7 +1,7 @@
1
1
  //#region src/utilities/metadata.ts
2
2
  const METADATA_KEY = "rx:metadata";
3
3
  function parseMetadataFromProps(props) {
4
- return { childType: props.childType };
4
+ return { childType: props.$type ?? props.childType };
5
5
  }
6
6
  function getMetadata(object) {
7
7
  return Reflect.getMetadata(METADATA_KEY, object) ?? null;
@@ -10,8 +10,10 @@ function setMetadata(object, value) {
10
10
  Reflect.defineMetadata(METADATA_KEY, value, object);
11
11
  }
12
12
  function setMetadataFromProps(object, props) {
13
- setMetadata(object, parseMetadataFromProps(props));
13
+ setMetadata(object, {
14
+ ...getMetadata(object),
15
+ ...parseMetadataFromProps(props)
16
+ });
14
17
  }
15
-
16
18
  //#endregion
17
- export { getMetadata, setMetadataFromProps };
19
+ export { getMetadata, setMetadata, setMetadataFromProps };
@@ -0,0 +1,31 @@
1
+ import { getMetadata, setMetadata } from "./metadata.mjs";
2
+ import { insertBefore, removeChild } from "./children.mjs";
3
+ //#region src/utilities/suspend.ts
4
+ /**
5
+ * Hide an instance by removing it from its parent and storing its parent and next sibling in metadata.
6
+ */
7
+ function hideInstance(instance) {
8
+ const parent = instance.get_parent();
9
+ if (!parent) return;
10
+ let meta = getMetadata(instance);
11
+ meta ??= {};
12
+ meta.suspenseState = {
13
+ parent,
14
+ nextSibling: instance.get_next_sibling()
15
+ };
16
+ setMetadata(instance, meta);
17
+ removeChild(parent, instance);
18
+ }
19
+ /**
20
+ * Restore an instance by inserting it after its stored next sibling in its stored parent.
21
+ */
22
+ function unhideInstance(instance) {
23
+ let meta = getMetadata(instance);
24
+ if (!meta?.suspenseState) return;
25
+ const { parent, nextSibling } = meta.suspenseState;
26
+ insertBefore(parent, instance, nextSibling);
27
+ if (meta) delete meta.suspenseState;
28
+ setMetadata(instance, meta);
29
+ }
30
+ //#endregion
31
+ export { hideInstance, unhideInstance };
@@ -2,6 +2,5 @@
2
2
  function getGtype(obj) {
3
3
  return obj.constructor.$gtype;
4
4
  }
5
-
6
5
  //#endregion
7
- export { getGtype };
6
+ export { getGtype };
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@peachy/react",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "Run GJS applications with react",
5
5
  "license": "MIT",
6
6
  "author": "Angelo Verlain <hey@vixalien.com>",
7
7
  "files": [
8
8
  "dist",
9
- "tsconfig.json"
9
+ "tsconfig.json",
10
+ "tsconfig.app.json"
10
11
  ],
11
12
  "main": "./dist/index.mjs",
12
13
  "exports": {
@@ -18,21 +19,29 @@
18
19
  "import": "./dist/*.mjs",
19
20
  "types": "./dist/*.d.mts"
20
21
  },
21
- "./tsconfig": "./tsconfig.json"
22
+ "./tsconfig.lib": "./tsconfig.json",
23
+ "./tsconfig.app": "./tsconfig.app.json",
24
+ "./types": {
25
+ "types": "./dist/env.d.mts"
26
+ }
22
27
  },
23
28
  "dependencies": {
24
- "@peachy/types": "^0.0.0-girgen.2",
25
- "react": "^19.2.4",
29
+ "react": "^19.2.5",
26
30
  "react-reconciler": "^0.33.0",
27
31
  "reflect-metadata": "^0.2.2",
28
- "@peachy/core": "0.0.11"
32
+ "@peachy/core": "0.0.13",
33
+ "@peachy/polyfills": "0.0.13"
29
34
  },
30
35
  "devDependencies": {
31
- "@types/node": "^25.2.1",
32
- "@types/react": "^19.2.13",
36
+ "@peachy/types": "^2026.4.9",
37
+ "@types/node": "^25.5.2",
38
+ "@types/react": "^19.2.14",
33
39
  "@types/react-reconciler": "^0.33.0",
34
- "tsdown": "0.20.3",
35
- "typescript": "^5.9.3"
40
+ "tsdown": "0.21.7",
41
+ "typescript": "^6.0.2"
42
+ },
43
+ "peerDependencies": {
44
+ "@peachy/types": "^2026.3.10"
36
45
  },
37
46
  "scripts": {
38
47
  "build": "tsdown"
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "@peachy/core/tsconfig.app",
4
+ "compilerOptions": {
5
+ "jsx": "react-jsx",
6
+ "jsxImportSource": "@peachy/react",
7
+ "types": ["@peachy/react/types"]
8
+ },
9
+ "include": ["@peachy/react/types", "${configDir}/src"]
10
+ }
package/tsconfig.json CHANGED
@@ -1,18 +1,10 @@
1
1
  {
2
- "extends": "@peachy/core/tsconfig",
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "@peachy/core/tsconfig.lib",
3
4
  "compilerOptions": {
4
5
  "jsx": "react-jsx",
5
- "jsxImportSource": "@peachy/react"
6
+ "jsxImportSource": "@peachy/react",
7
+ "types": ["@peachy/react/types", "node"]
6
8
  },
7
- "include": [
8
- // when installed locally
9
- "./node_modules/@peachy/types/types/index.d.ts",
10
- "./node_modules/@peachy/core/node_modules/@peachy/plugin-resources/src/modules.d.ts",
11
- "./node_modules/@peachy/core/node_modules/@peachy/plugin-css/src/modules.d.ts",
12
- // when installed via npm/pnpm
13
- "../types/types/index.d.ts",
14
- "../plugin-resources/src/modules.d.ts",
15
- "../plugin-css/src/modules.d.ts",
16
- "${configDir}/src/**/*"
17
- ]
9
+ "include": ["@peachy/react/types", "${configDir}/src"]
18
10
  }