@peachy/react 0.0.1
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 +90 -0
- package/dist/extra.d.mts +11 -0
- package/dist/extra.mjs +20 -0
- package/dist/global.d.mts +36 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +123 -0
- package/dist/jsx-dev-runtime.d.mts +6 -0
- package/dist/jsx-dev-runtime.mjs +11 -0
- package/dist/jsx-runtime.d.mts +9 -0
- package/dist/jsx-runtime.mjs +16 -0
- package/dist/jsx-utils.d.mts +4 -0
- package/dist/jsx-utils.mjs +18 -0
- package/dist/type-map.d.mts +4 -0
- package/dist/type-map.mjs +5 -0
- package/dist/types.d.mts +8 -0
- package/dist/utilities/children.mjs +53 -0
- package/dist/utilities/diff.mjs +45 -0
- package/dist/utilities/metadata.mjs +17 -0
- package/dist/utilities/type.mjs +7 -0
- package/package.json +40 -0
- package/tsconfig.json +11 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @peachy/react
|
|
2
|
+
|
|
3
|
+
This package contains a React renderer for GTK.
|
|
4
|
+
|
|
5
|
+
It implements a custom react-reconciler, which is responsible for rendering React components into the GTK "DOM".
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
You can install this package with npm:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @peachy/react @peachy/core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
For typescript, you will need to install the GTK types:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @peachy/types
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Then setup your config file
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
// tsconfig.json
|
|
25
|
+
{
|
|
26
|
+
"extends": "@peachy/react/tsconfig",
|
|
27
|
+
"include": ["@peachy/types"]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
Here is a basic example that creates a GTK application window with a label:
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import Gtk from "gi://Gtk?version=4.0";
|
|
38
|
+
import { render } from "@peachy/react";
|
|
39
|
+
|
|
40
|
+
const app = Gtk.Application.new(
|
|
41
|
+
"com.hello.world",
|
|
42
|
+
Gio.ApplicationFlags.DEFAULT_FLAGS,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
app.connect("activate", () => {
|
|
46
|
+
const app_window = Gtk.ApplicationWindow.new(app);
|
|
47
|
+
|
|
48
|
+
render(<Gtk.Label label="Hello, World!" />, app_window);
|
|
49
|
+
|
|
50
|
+
app_window.present();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
app.run([]);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
You can also create reusable components using React's component system. For example, you can create a custom button component:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import Gtk from "gi://Gtk?version=4.0";
|
|
60
|
+
import { render } from "@peachy/react";
|
|
61
|
+
|
|
62
|
+
const Button = ({ label, onClick }) => (
|
|
63
|
+
<Gtk.Button label={label} onClick={onClick} />
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const app = Gtk.Application.new(
|
|
67
|
+
"com.hello.world",
|
|
68
|
+
Gio.ApplicationFlags.DEFAULT_FLAGS,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
app.connect("activate", () => {
|
|
72
|
+
const app_window = Gtk.ApplicationWindow.new(app);
|
|
73
|
+
|
|
74
|
+
render(
|
|
75
|
+
<Button label="Click me!" onClick={() => console.log("Button clicked")} />,
|
|
76
|
+
app_window
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
app_window.present();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
app.run([]);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## References
|
|
86
|
+
|
|
87
|
+
- https://github.com/VisualElectric/pixi-react
|
|
88
|
+
- react-reconciler
|
|
89
|
+
- https://github.com/samuelscheit/react-native-skia-list
|
|
90
|
+
- https://github.com/jiayihu/react-tiny-dom
|
package/dist/extra.d.mts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Gtk from "gi://Gtk?version=4.0";
|
|
2
|
+
|
|
3
|
+
//#region src/extra.d.ts
|
|
4
|
+
interface ReactionExtraProps<T extends Gtk.Widget> {
|
|
5
|
+
appendChild?(parentInstance: T, child: Gtk.Widget): void;
|
|
6
|
+
insertBefore?(parentInstance: T, child: Gtk.Widget, before: Gtk.Widget | null): void;
|
|
7
|
+
removeChild?(parentInstance: T, child: Gtk.Widget): void;
|
|
8
|
+
}
|
|
9
|
+
declare const extraMap: Map<GObject.GType, ReactionExtraProps<Gtk.Widget>>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { ReactionExtraProps, extraMap };
|
package/dist/extra.mjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getMetadata } from "./utilities/metadata.mjs";
|
|
2
|
+
import Gtk from "gi://Gtk?version=4.0";
|
|
3
|
+
|
|
4
|
+
//#region src/extra.ts
|
|
5
|
+
let builder;
|
|
6
|
+
const extraMap = new Map([[Gtk.Buildable.$gtype, { appendChild: (parentInstance, child) => {
|
|
7
|
+
builder ??= Gtk.Builder.new();
|
|
8
|
+
const metadata = getMetadata(child);
|
|
9
|
+
parentInstance.vfunc_add_child(builder, child, metadata?.childType ?? null);
|
|
10
|
+
} }], [Gtk.Window.$gtype, {
|
|
11
|
+
appendChild: (parentInstance, child) => {
|
|
12
|
+
parentInstance.set_child(child);
|
|
13
|
+
},
|
|
14
|
+
removeChild: (parentInstance) => {
|
|
15
|
+
parentInstance.set_child(null);
|
|
16
|
+
}
|
|
17
|
+
}]]);
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
export { extraMap };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Key, Ref } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/global.d.ts
|
|
4
|
+
declare global {
|
|
5
|
+
namespace JSX {
|
|
6
|
+
interface IntrinsicAttributes {
|
|
7
|
+
childType?: string;
|
|
8
|
+
ref?: Ref<any>;
|
|
9
|
+
key?: Key | null | undefined;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
declare module "gi://Gtk?version=4.0" {
|
|
14
|
+
namespace Gtk {
|
|
15
|
+
namespace Widget {
|
|
16
|
+
interface ConstructorProps {
|
|
17
|
+
/**
|
|
18
|
+
* React children
|
|
19
|
+
*/
|
|
20
|
+
children: any;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
declare module "gi://Gtk?version=3.0" {
|
|
26
|
+
namespace Gtk {
|
|
27
|
+
namespace Widget {
|
|
28
|
+
interface ConstructorProps {
|
|
29
|
+
/**
|
|
30
|
+
* React children
|
|
31
|
+
*/
|
|
32
|
+
children: any;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
package/dist/index.d.mts
ADDED
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { setMetadataFromProps } from "./utilities/metadata.mjs";
|
|
2
|
+
import "./global.d.mts";
|
|
3
|
+
import { typeMap } from "./type-map.mjs";
|
|
4
|
+
import { appendChild, insertBefore, removeChild } from "./utilities/children.mjs";
|
|
5
|
+
import { getEventListeners, getEventName, getProperties, updateWidget } from "./utilities/diff.mjs";
|
|
6
|
+
import Gtk from "gi://Gtk?version=4.0";
|
|
7
|
+
import "reflect-metadata";
|
|
8
|
+
import GLib from "gi://GLib?version=2.0";
|
|
9
|
+
import Reconciler from "react-reconciler";
|
|
10
|
+
import { DefaultEventPriority, NoEventPriority } from "react-reconciler/constants";
|
|
11
|
+
|
|
12
|
+
//#region src/index.ts
|
|
13
|
+
const emptyObject = {};
|
|
14
|
+
let updatePriority = NoEventPriority;
|
|
15
|
+
const reconciler = Reconciler({
|
|
16
|
+
appendInitialChild(parentInstance, child) {
|
|
17
|
+
appendChild(parentInstance, child);
|
|
18
|
+
},
|
|
19
|
+
createInstance(type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
|
|
20
|
+
const klass = typeMap.get(type);
|
|
21
|
+
if (!klass) throw new Error(`Unknown type: ${type}`);
|
|
22
|
+
return new klass(getProperties(props));
|
|
23
|
+
},
|
|
24
|
+
createTextInstance(text, rootContainerInstance, internalInstanceHandle) {
|
|
25
|
+
return Gtk.Label.new(text);
|
|
26
|
+
},
|
|
27
|
+
finalizeInitialChildren(widget, type, props) {
|
|
28
|
+
const events = getEventListeners(props);
|
|
29
|
+
Object.keys(events).forEach((name) => {
|
|
30
|
+
const eventType = getEventName(name);
|
|
31
|
+
widget.connect(eventType, events[name]);
|
|
32
|
+
});
|
|
33
|
+
setMetadataFromProps(widget, props);
|
|
34
|
+
return false;
|
|
35
|
+
},
|
|
36
|
+
getPublicInstance(inst) {
|
|
37
|
+
return inst;
|
|
38
|
+
},
|
|
39
|
+
prepareForCommit() {
|
|
40
|
+
return null;
|
|
41
|
+
},
|
|
42
|
+
resetAfterCommit() {},
|
|
43
|
+
getRootHostContext(rootInstance) {
|
|
44
|
+
return emptyObject;
|
|
45
|
+
},
|
|
46
|
+
getChildHostContext(parentHostContext, type) {
|
|
47
|
+
return emptyObject;
|
|
48
|
+
},
|
|
49
|
+
shouldSetTextContent(type, props) {
|
|
50
|
+
return false;
|
|
51
|
+
},
|
|
52
|
+
supportsMutation: true,
|
|
53
|
+
supportsHydration: false,
|
|
54
|
+
supportsPersistence: false,
|
|
55
|
+
supportsMicrotasks: true,
|
|
56
|
+
scheduleTimeout: (fn, delay) => {
|
|
57
|
+
GLib.timeout_add(GLib.PRIORITY_DEFAULT, delay, () => {
|
|
58
|
+
fn();
|
|
59
|
+
return GLib.SOURCE_REMOVE;
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
scheduleMicrotask: (fn) => {
|
|
63
|
+
GLib.idle_add(GLib.PRIORITY_HIGH_IDLE, () => {
|
|
64
|
+
fn();
|
|
65
|
+
return GLib.SOURCE_REMOVE;
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
removeChild(parentInstance, child) {
|
|
69
|
+
removeChild(parentInstance, child);
|
|
70
|
+
},
|
|
71
|
+
removeChildFromContainer(parentInstance, child) {
|
|
72
|
+
removeChild(parentInstance, child);
|
|
73
|
+
},
|
|
74
|
+
insertBefore(parentInstance, child, beforeChild) {
|
|
75
|
+
insertBefore(parentInstance, child, beforeChild);
|
|
76
|
+
},
|
|
77
|
+
insertInContainerBefore(parentInstance, child, beforeChild) {
|
|
78
|
+
insertBefore(parentInstance, child, beforeChild);
|
|
79
|
+
},
|
|
80
|
+
clearContainer(container) {},
|
|
81
|
+
appendChild(parentInstance, child) {
|
|
82
|
+
appendChild(parentInstance, child);
|
|
83
|
+
},
|
|
84
|
+
appendChildToContainer(container, child) {
|
|
85
|
+
appendChild(container, child);
|
|
86
|
+
},
|
|
87
|
+
detachDeletedInstance(node) {
|
|
88
|
+
node.unparent();
|
|
89
|
+
},
|
|
90
|
+
commitUpdate(widget, type, oldProps, newProps, internalInstanceHandle) {
|
|
91
|
+
updateWidget(widget, oldProps, newProps);
|
|
92
|
+
},
|
|
93
|
+
commitTextUpdate(textInstance, oldText, newText) {},
|
|
94
|
+
resolveUpdatePriority: function() {
|
|
95
|
+
if (updatePriority !== NoEventPriority) return updatePriority;
|
|
96
|
+
return DefaultEventPriority;
|
|
97
|
+
},
|
|
98
|
+
setCurrentUpdatePriority: function(newPriority) {
|
|
99
|
+
updatePriority = newPriority;
|
|
100
|
+
},
|
|
101
|
+
getCurrentUpdatePriority: function() {
|
|
102
|
+
return updatePriority;
|
|
103
|
+
},
|
|
104
|
+
resolveEventTimeStamp() {
|
|
105
|
+
return -1.1;
|
|
106
|
+
},
|
|
107
|
+
resolveEventType() {
|
|
108
|
+
return null;
|
|
109
|
+
},
|
|
110
|
+
trackSchedulerEvent() {}
|
|
111
|
+
});
|
|
112
|
+
const render = (jsx, root, callback) => {
|
|
113
|
+
const container = reconciler.createContainer(root, 0, null, false, null, "peachy", console.error, console.error, console.error, () => {}, null);
|
|
114
|
+
reconciler.updateContainer(jsx, container, null, callback);
|
|
115
|
+
};
|
|
116
|
+
reconciler.injectIntoDevTools({
|
|
117
|
+
bundleType: process.env.NODE_ENV === "development" ? 1 : 0,
|
|
118
|
+
version: "0.0.1",
|
|
119
|
+
rendererPackageName: "peachy"
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
export { render };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { transformType } from "./jsx-utils.mjs";
|
|
2
|
+
import * as React from "react/jsx-dev-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/jsx-dev-runtime.ts
|
|
5
|
+
const jsxDEV = (type, ...args) => {
|
|
6
|
+
const transformedType = transformType(type);
|
|
7
|
+
return React.jsxDEV(transformedType, ...args);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { jsxDEV };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as react0 from "react";
|
|
2
|
+
import * as React from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/jsx-runtime.d.ts
|
|
5
|
+
declare const jsx: typeof React.jsx;
|
|
6
|
+
declare const jsxs: typeof React.jsxs;
|
|
7
|
+
declare const Fragment: react0.ExoticComponent<react0.FragmentProps>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { Fragment, jsx, jsxs };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { transformType } from "./jsx-utils.mjs";
|
|
2
|
+
import * as React from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/jsx-runtime.ts
|
|
5
|
+
const jsx = (type, ...args) => {
|
|
6
|
+
const transformedType = transformType(type);
|
|
7
|
+
return React.jsx(transformedType, ...args);
|
|
8
|
+
};
|
|
9
|
+
const jsxs = (type, ...args) => {
|
|
10
|
+
const transformedType = transformType(type);
|
|
11
|
+
return React.jsxs(transformedType, ...args);
|
|
12
|
+
};
|
|
13
|
+
const Fragment = React.Fragment;
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Fragment, jsx, jsxs };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { typeMap } from "./type-map.mjs";
|
|
2
|
+
import GObject from "gi://GObject?version=2.0";
|
|
3
|
+
|
|
4
|
+
//#region src/jsx-utils.ts
|
|
5
|
+
function isGtkWidgetClass(type) {
|
|
6
|
+
return typeof type === "function" && type.prototype instanceof GObject.Object;
|
|
7
|
+
}
|
|
8
|
+
const transformType = (type) => {
|
|
9
|
+
if (isGtkWidgetClass(type)) {
|
|
10
|
+
const type_name = GObject.type_name(type.$gtype);
|
|
11
|
+
if (!typeMap.has(type_name)) typeMap.set(type_name, type);
|
|
12
|
+
return type_name;
|
|
13
|
+
}
|
|
14
|
+
return type;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { transformType };
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { extraMap } from "../extra.mjs";
|
|
2
|
+
import { getGtype } from "./type.mjs";
|
|
3
|
+
import GObject from "gi://GObject?version=2.0";
|
|
4
|
+
|
|
5
|
+
//#region src/utilities/children.ts
|
|
6
|
+
function _appendChildIfPossible(parentInstance, child) {
|
|
7
|
+
const gtype = getGtype(parentInstance);
|
|
8
|
+
for (const [type, props] of extraMap) if (GObject.type_is_a(gtype, type)) {
|
|
9
|
+
if (props.appendChild) {
|
|
10
|
+
props.appendChild(parentInstance, child);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if ("child" in parentInstance) {
|
|
15
|
+
parentInstance.child = child;
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if ("content" in parentInstance) {
|
|
19
|
+
parentInstance.content = child;
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
function appendChild(parentInstance, child) {
|
|
25
|
+
if (_appendChildIfPossible(parentInstance, child)) return;
|
|
26
|
+
child.set_parent(parentInstance);
|
|
27
|
+
}
|
|
28
|
+
function insertBefore(parentInstance, child, sibling) {
|
|
29
|
+
const gtype = getGtype(parentInstance);
|
|
30
|
+
for (const [type, props] of extraMap) if (GObject.type_is_a(gtype, type)) {
|
|
31
|
+
if (props.insertBefore) return props.insertBefore(parentInstance, child, sibling);
|
|
32
|
+
}
|
|
33
|
+
if (_appendChildIfPossible(parentInstance, child)) return;
|
|
34
|
+
child.insert_before(parentInstance, sibling);
|
|
35
|
+
}
|
|
36
|
+
function removeChild(parentInstance, child) {
|
|
37
|
+
const gtype = getGtype(parentInstance);
|
|
38
|
+
for (const [type, props] of extraMap) if (GObject.type_is_a(gtype, type)) {
|
|
39
|
+
if (props.removeChild) return props.removeChild(parentInstance, child);
|
|
40
|
+
}
|
|
41
|
+
if ("child" in parentInstance) {
|
|
42
|
+
parentInstance.child = void 0;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if ("content" in parentInstance) {
|
|
46
|
+
parentInstance.content = void 0;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
child.unparent();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
export { appendChild, insertBefore, removeChild };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { setMetadataFromProps } from "./metadata.mjs";
|
|
2
|
+
import GObject from "gi://GObject?version=2.0";
|
|
3
|
+
|
|
4
|
+
//#region src/utilities/diff.ts
|
|
5
|
+
const INTERNAL_PROP_NAMES = [
|
|
6
|
+
"childType",
|
|
7
|
+
"ref",
|
|
8
|
+
"key"
|
|
9
|
+
];
|
|
10
|
+
const getEventName = (event) => event.substring(2).replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "").replace(/:-/, "::");
|
|
11
|
+
const isEvent = (key) => key.startsWith("on");
|
|
12
|
+
const isProperty = (key) => key !== "children" && !isEvent(key) && !INTERNAL_PROP_NAMES.includes(key);
|
|
13
|
+
const isNew = (prev, next) => (key) => prev[key] !== next[key];
|
|
14
|
+
const isGone = (prev, next) => (key) => !(key in next);
|
|
15
|
+
function updateWidget(widget, prev, next) {
|
|
16
|
+
Object.keys(prev).filter(isEvent).filter((key) => !(key in next) || isNew(prev, next)(key)).forEach((name) => {
|
|
17
|
+
if (GObject.signal_handlers_disconnect_by_func(widget, prev[name]) === 0) console.warn(`No signal handler found for ${name}`);
|
|
18
|
+
});
|
|
19
|
+
Object.keys(prev).filter(isProperty).filter(isGone(prev, next)).forEach((name) => {
|
|
20
|
+
widget[name] = void 0;
|
|
21
|
+
});
|
|
22
|
+
Object.keys(next).filter(isProperty).filter(isNew(prev, next)).forEach((name) => {
|
|
23
|
+
widget[name] = next[name];
|
|
24
|
+
});
|
|
25
|
+
Object.keys(next).filter(isEvent).filter(isNew(prev, next)).forEach((name) => {
|
|
26
|
+
const eventType = getEventName(name);
|
|
27
|
+
widget.connect(eventType, next[name]);
|
|
28
|
+
});
|
|
29
|
+
setMetadataFromProps(widget, next);
|
|
30
|
+
}
|
|
31
|
+
function getProperties(props) {
|
|
32
|
+
return Object.keys(props).filter(isProperty).reduce((acc, key) => {
|
|
33
|
+
acc[key] = props[key];
|
|
34
|
+
return acc;
|
|
35
|
+
}, {});
|
|
36
|
+
}
|
|
37
|
+
function getEventListeners(props) {
|
|
38
|
+
return Object.keys(props).filter(isEvent).reduce((acc, key) => {
|
|
39
|
+
acc[key] = props[key];
|
|
40
|
+
return acc;
|
|
41
|
+
}, {});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
export { getEventListeners, getEventName, getProperties, updateWidget };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/utilities/metadata.ts
|
|
2
|
+
const METADATA_KEY = "rx:metadata";
|
|
3
|
+
function parseMetadataFromProps(props) {
|
|
4
|
+
return { childType: props.childType };
|
|
5
|
+
}
|
|
6
|
+
function getMetadata(object) {
|
|
7
|
+
return Reflect.getMetadata(METADATA_KEY, object) ?? null;
|
|
8
|
+
}
|
|
9
|
+
function setMetadata(object, value) {
|
|
10
|
+
Reflect.defineMetadata(METADATA_KEY, value, object);
|
|
11
|
+
}
|
|
12
|
+
function setMetadataFromProps(object, props) {
|
|
13
|
+
setMetadata(object, parseMetadataFromProps(props));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { getMetadata, setMetadataFromProps };
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@peachy/react",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Run GJS applications with react",
|
|
5
|
+
"main": "./dist/index.mjs",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.mts"
|
|
10
|
+
},
|
|
11
|
+
"./*": {
|
|
12
|
+
"import": "./dist/*.mjs",
|
|
13
|
+
"types": "./dist/*.d.mts"
|
|
14
|
+
},
|
|
15
|
+
"./tsconfig": "./tsconfig.json"
|
|
16
|
+
},
|
|
17
|
+
"author": "Angelo Verlain <hey@vixalien.com>",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@peachy/types": "^2025.1.18",
|
|
20
|
+
"react": "^19.2.0",
|
|
21
|
+
"react-reconciler": "^0.33.0",
|
|
22
|
+
"reflect-metadata": "^0.2.2",
|
|
23
|
+
"@peachy/core": "0.0.1"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/react": "^19.2.7",
|
|
27
|
+
"@types/react-reconciler": "^0.32.3",
|
|
28
|
+
"tsdown": "0.20.0-beta.3",
|
|
29
|
+
"typescript": "^5.9.3"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"tsconfig.json"
|
|
34
|
+
],
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsdown"
|
|
38
|
+
},
|
|
39
|
+
"types": "./dist/index.d.mts"
|
|
40
|
+
}
|
package/tsconfig.json
ADDED