onejs-react 0.1.15 → 0.1.16
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/package.json +1 -1
- package/src/components.tsx +38 -1
- package/src/host-config.ts +50 -0
- package/src/index.ts +4 -0
package/package.json
CHANGED
package/src/components.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { forwardRef, useMemo, type ReactElement, type Ref } from 'react';
|
|
1
|
+
import { forwardRef, createElement, useMemo, type ReactElement, type Ref } from 'react';
|
|
2
2
|
import type {
|
|
3
|
+
BaseProps,
|
|
3
4
|
ViewProps,
|
|
4
5
|
TextProps,
|
|
5
6
|
LabelProps,
|
|
@@ -172,3 +173,39 @@ export const ListView = forwardRef<VisualElement, ListViewProps>((props, ref) =>
|
|
|
172
173
|
return <ojs-listview ref={ref} {...props} />;
|
|
173
174
|
});
|
|
174
175
|
ListView.displayName = 'ListView';
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Create a typed React component for a registered custom element.
|
|
179
|
+
* Use with `registerElement()` to add custom C# VisualElement types to React.
|
|
180
|
+
*
|
|
181
|
+
* @param name - Element name matching what was passed to registerElement()
|
|
182
|
+
* @param displayName - Optional display name for React DevTools
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* import { registerElement, createComponent } from "onejs-react"
|
|
186
|
+
* import { BaseProps, VisualElement } from "onejs-react"
|
|
187
|
+
*
|
|
188
|
+
* // Define props for your custom element
|
|
189
|
+
* interface RadialProgressProps extends BaseProps {
|
|
190
|
+
* progress?: number
|
|
191
|
+
* trackColor?: string
|
|
192
|
+
* }
|
|
193
|
+
*
|
|
194
|
+
* // Register and create the component
|
|
195
|
+
* registerElement("radial-progress", CS.MyGame.UI.RadialProgress)
|
|
196
|
+
* export const RadialProgress = createComponent<RadialProgressProps>("radial-progress")
|
|
197
|
+
*
|
|
198
|
+
* // Use in JSX like any React component
|
|
199
|
+
* <RadialProgress progress={0.75} trackColor="#333" style={{ width: 100, height: 100 }} />
|
|
200
|
+
*/
|
|
201
|
+
export function createComponent<P extends BaseProps = BaseProps>(
|
|
202
|
+
name: string,
|
|
203
|
+
displayName?: string
|
|
204
|
+
) {
|
|
205
|
+
const type = name.startsWith('ojs-') ? name : `ojs-${name}`;
|
|
206
|
+
const Component = forwardRef<VisualElement, P>((props, ref) => {
|
|
207
|
+
return createElement(type, { ...props, ref });
|
|
208
|
+
});
|
|
209
|
+
Component.displayName = displayName || name;
|
|
210
|
+
return Component;
|
|
211
|
+
}
|
package/src/host-config.ts
CHANGED
|
@@ -175,6 +175,35 @@ const TYPE_MAP: Record<string, () => CSObject> = {
|
|
|
175
175
|
'ojs-listview': () => new CS.UnityEngine.UIElements.ListView(),
|
|
176
176
|
};
|
|
177
177
|
|
|
178
|
+
// Built-in types with specific prop handling in applyComponentProps
|
|
179
|
+
const BUILT_IN_TYPES = new Set(Object.keys(TYPE_MAP));
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Register a custom VisualElement type for use in React JSX.
|
|
183
|
+
*
|
|
184
|
+
* @param name - Element name (with or without 'ojs-' prefix)
|
|
185
|
+
* @param constructor - C# constructor reference (e.g., CS.MyNamespace.MyWidget)
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* import { registerElement, createComponent } from "onejs-react"
|
|
189
|
+
*
|
|
190
|
+
* // Register the custom element
|
|
191
|
+
* registerElement("radial-progress", CS.MyGame.UI.RadialProgress)
|
|
192
|
+
*
|
|
193
|
+
* // Create a typed React component for it
|
|
194
|
+
* const RadialProgress = createComponent<RadialProgressProps>("radial-progress")
|
|
195
|
+
*
|
|
196
|
+
* // Use in JSX
|
|
197
|
+
* <RadialProgress progress={0.75} />
|
|
198
|
+
*/
|
|
199
|
+
export function registerElement(name: string, constructor: new (...args: any[]) => any): void {
|
|
200
|
+
const key = name.startsWith('ojs-') ? name : `ojs-${name}`;
|
|
201
|
+
if (TYPE_MAP[key]) {
|
|
202
|
+
console.error(`registerElement: "${name}" is already registered. Overwriting.`);
|
|
203
|
+
}
|
|
204
|
+
TYPE_MAP[key] = () => new constructor();
|
|
205
|
+
}
|
|
206
|
+
|
|
178
207
|
// Event prop to event type mapping
|
|
179
208
|
const EVENT_PROPS: Record<string, string> = {
|
|
180
209
|
// Click
|
|
@@ -728,8 +757,29 @@ function applyListViewProps(element: CSListView, props: Record<string, unknown>)
|
|
|
728
757
|
setEnumProp(element, 'showAlternatingRowBackgrounds', props, 'showAlternatingRowBackgrounds', UIE.AlternatingRowBackground);
|
|
729
758
|
}
|
|
730
759
|
|
|
760
|
+
// Props handled by the reconciler infrastructure - not forwarded to C# elements
|
|
761
|
+
const RESERVED_PROPS = new Set([
|
|
762
|
+
'children', 'key', 'ref', 'style', 'className', 'pickingMode',
|
|
763
|
+
'onGenerateVisualContent',
|
|
764
|
+
...Object.keys(EVENT_PROPS),
|
|
765
|
+
]);
|
|
766
|
+
|
|
767
|
+
// Forward non-reserved props directly to C# element (for custom elements)
|
|
768
|
+
function applyCustomProps(element: CSObject, props: Record<string, unknown>) {
|
|
769
|
+
for (const [key, value] of Object.entries(props)) {
|
|
770
|
+
if (value === undefined || RESERVED_PROPS.has(key)) continue;
|
|
771
|
+
(element as any)[key] = value;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
731
775
|
// Apply component-specific props based on element type
|
|
732
776
|
function applyComponentProps(element: CSObject, type: string, props: Record<string, unknown>) {
|
|
777
|
+
// Custom elements: forward all non-reserved props directly to C# element
|
|
778
|
+
if (!BUILT_IN_TYPES.has(type)) {
|
|
779
|
+
applyCustomProps(element, props);
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
|
|
733
783
|
// For Slider, apply range props (lowValue/highValue) BEFORE value
|
|
734
784
|
// Unity's Slider clamps value to [lowValue, highValue], so range must be set first
|
|
735
785
|
if (type === 'ojs-slider') {
|
package/src/index.ts
CHANGED
|
@@ -11,8 +11,12 @@ export {
|
|
|
11
11
|
Image,
|
|
12
12
|
ListView,
|
|
13
13
|
clearImageCache,
|
|
14
|
+
createComponent,
|
|
14
15
|
} from './components';
|
|
15
16
|
|
|
17
|
+
// Custom Element Registration
|
|
18
|
+
export { registerElement } from './host-config';
|
|
19
|
+
|
|
16
20
|
// Renderer
|
|
17
21
|
export { render, unmount, flushSync, batchedUpdates, getDebugInfo } from './renderer';
|
|
18
22
|
|