5
bun.lock
5
bun.lock
@@ -39,6 +39,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-reconciler": "~0.32.0",
|
"react-reconciler": "~0.32.0",
|
||||||
|
"type-fest": "^5.3.1",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react-reconciler": "~0.32.0",
|
"@types/react-reconciler": "~0.32.0",
|
||||||
@@ -320,6 +321,8 @@
|
|||||||
|
|
||||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||||
|
|
||||||
|
"tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
|
||||||
|
|
||||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||||
|
|
||||||
"turbo": ["turbo@2.7.2", "", { "optionalDependencies": { "turbo-darwin-64": "2.7.2", "turbo-darwin-arm64": "2.7.2", "turbo-linux-64": "2.7.2", "turbo-linux-arm64": "2.7.2", "turbo-windows-64": "2.7.2", "turbo-windows-arm64": "2.7.2" }, "bin": { "turbo": "bin/turbo" } }, "sha512-5JIA5aYBAJSAhrhbyag1ZuMSgUZnHtI+Sq3H8D3an4fL8PeF+L1yYvbEJg47akP1PFfATMf5ehkqFnxfkmuwZQ=="],
|
"turbo": ["turbo@2.7.2", "", { "optionalDependencies": { "turbo-darwin-64": "2.7.2", "turbo-darwin-arm64": "2.7.2", "turbo-linux-64": "2.7.2", "turbo-linux-arm64": "2.7.2", "turbo-windows-64": "2.7.2", "turbo-windows-arm64": "2.7.2" }, "bin": { "turbo": "bin/turbo" } }, "sha512-5JIA5aYBAJSAhrhbyag1ZuMSgUZnHtI+Sq3H8D3an4fL8PeF+L1yYvbEJg47akP1PFfATMf5ehkqFnxfkmuwZQ=="],
|
||||||
@@ -336,6 +339,8 @@
|
|||||||
|
|
||||||
"turbo-windows-arm64": ["turbo-windows-arm64@2.7.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-tcnHvBhO515OheIFWdxA+qUvZzNqqcHbLVFc1+n+TJ1rrp8prYicQtbtmsiKgMvr/54jb9jOabU62URAobnB7g=="],
|
"turbo-windows-arm64": ["turbo-windows-arm64@2.7.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-tcnHvBhO515OheIFWdxA+qUvZzNqqcHbLVFc1+n+TJ1rrp8prYicQtbtmsiKgMvr/54jb9jOabU62URAobnB7g=="],
|
||||||
|
|
||||||
|
"type-fest": ["type-fest@5.3.1", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-VCn+LMHbd4t6sF3wfU/+HKT63C9OoyrSIf4b+vtWHpt2U7/4InZG467YDNMFMR70DdHjAdpPWmw2lzRdg0Xqqg=="],
|
||||||
|
|
||||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
"unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
|
"unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
|
||||||
|
|||||||
@@ -41,7 +41,8 @@
|
|||||||
"@types/react-reconciler": "~0.32.0"
|
"@types/react-reconciler": "~0.32.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-reconciler": "~0.32.0"
|
"react-reconciler": "~0.32.0",
|
||||||
|
"type-fest": "^5.3.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^19.2.0",
|
"@types/react": "^19.2.0",
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { Predicate, String } from "effect"
|
import { ClassDB, Node, type NodePathMap } from "godot"
|
||||||
import { ClassDB, Node } from "godot"
|
|
||||||
import ReactReconciler from "react-reconciler"
|
import ReactReconciler from "react-reconciler"
|
||||||
import { DefaultEventPriority } from "react-reconciler/constants"
|
import { camelToSnake, hasProperty, snakeToPascal } from "./utils.js"
|
||||||
|
|
||||||
|
|
||||||
|
const DefaultEventPriority = 32
|
||||||
|
|
||||||
|
|
||||||
export const make = () => {
|
export const make = () => {
|
||||||
@@ -11,13 +13,13 @@ export const make = () => {
|
|||||||
return ReactReconciler<
|
return ReactReconciler<
|
||||||
string,
|
string,
|
||||||
Record<string, unknown>,
|
Record<string, unknown>,
|
||||||
Node,
|
Node<NodePathMap>,
|
||||||
Node,
|
Node<NodePathMap>,
|
||||||
Node,
|
Node<NodePathMap>,
|
||||||
Node,
|
Node<NodePathMap>,
|
||||||
Node,
|
Node<NodePathMap>,
|
||||||
Node,
|
Node<NodePathMap>,
|
||||||
Node,
|
Node<NodePathMap>,
|
||||||
unknown,
|
unknown,
|
||||||
unknown,
|
unknown,
|
||||||
unknown,
|
unknown,
|
||||||
@@ -29,12 +31,12 @@ export const make = () => {
|
|||||||
createInstance(type, props) {
|
createInstance(type, props) {
|
||||||
let instance: Node
|
let instance: Node
|
||||||
if (type === "custom") {
|
if (type === "custom") {
|
||||||
if (!Predicate.hasProperty(props, "class"))
|
if (!hasProperty(props, "class"))
|
||||||
throw new Error("Property 'class' required when using the 'custom' intrinsic type")
|
throw new Error("Property 'class' required when using the 'custom' intrinsic type")
|
||||||
instance = new (props.class as any)()
|
instance = new (props.class as any)()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const className = String.capitalize(type)
|
const className = snakeToPascal(camelToSnake(type))
|
||||||
if (!ClassDB.class_exists(className))
|
if (!ClassDB.class_exists(className))
|
||||||
throw new Error(`Class is invalid: '${className}' (declared as '${type}') is not a valid engine or GDExtension class`)
|
throw new Error(`Class is invalid: '${className}' (declared as '${type}') is not a valid engine or GDExtension class`)
|
||||||
instance = ClassDB.instantiate(className)
|
instance = ClassDB.instantiate(className)
|
||||||
@@ -79,14 +81,14 @@ export const make = () => {
|
|||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
|
|
||||||
prepareForCommit() {},
|
prepareForCommit() { return null },
|
||||||
resetAfterCommit() {},
|
resetAfterCommit() {},
|
||||||
|
|
||||||
getRootHostContext() {
|
getRootHostContext() {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
|
||||||
getChildHostContext(parentHostContext, type, rootContainer) {
|
getChildHostContext(parentHostContext, _type, _rootContainer) {
|
||||||
return parentHostContext
|
return parentHostContext
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -103,7 +105,7 @@ export const make = () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getPublicInstance(instance) {
|
getPublicInstance(instance) {
|
||||||
return instance;
|
return instance
|
||||||
},
|
},
|
||||||
|
|
||||||
resolveUpdatePriority() {
|
resolveUpdatePriority() {
|
||||||
@@ -142,12 +144,12 @@ export const make = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const applyNextProps = (instance: Node, nextProps: Record<string, unknown>) => {
|
const applyNextProps = (instance: Node<NodePathMap>, nextProps: Record<string, unknown>) => {
|
||||||
Object.keys(nextProps).forEach(name => {
|
Object.keys(nextProps).forEach(name => {
|
||||||
(instance as any)[name] = nextProps[name]
|
(instance as any)[name] = nextProps[name]
|
||||||
})
|
})
|
||||||
|
|
||||||
if (Predicate.hasProperty(nextProps, "name")) {
|
if (hasProperty(nextProps, "name")) {
|
||||||
if (typeof nextProps.name !== "string")
|
if (typeof nextProps.name !== "string")
|
||||||
throw new Error("Prop 'name' should be a string")
|
throw new Error("Prop 'name' should be a string")
|
||||||
instance.set_name(nextProps.name)
|
instance.set_name(nextProps.name)
|
||||||
|
|||||||
16
packages/react-godot-renderer/src/utils.ts
Normal file
16
packages/react-godot-renderer/src/utils.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
export const isRecordOrArray = (input: unknown): input is { [x: PropertyKey]: unknown } =>
|
||||||
|
typeof input === "object" && input !== null
|
||||||
|
// biome-ignore lint/complexity/noBannedTypes: it's completely fine
|
||||||
|
export const isFunction = (input: unknown): input is Function => typeof input === "function"
|
||||||
|
export const isObject = (input: unknown): input is object => isRecordOrArray(input) || isFunction(input)
|
||||||
|
export const hasProperty = <P extends PropertyKey>(self: unknown, property: P): self is { [K in P]: unknown } =>
|
||||||
|
isObject(self) && (property in self)
|
||||||
|
|
||||||
|
export const camelToSnake = (self: string): string => self.replace(/([A-Z])/g, "_$1").toLowerCase()
|
||||||
|
export const snakeToPascal = (self: string): string => {
|
||||||
|
let str = self[0].toUpperCase()
|
||||||
|
for (let i = 1; i < self.length; i++) {
|
||||||
|
str += self[i] === "_" ? self[++i].toUpperCase() : self[i]
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user