1- import type { ComponentProps } from "react " ;
1+ import { ContainerBase , ContainerConfig } from "../ui/Container " ;
22import { Instance } from "../ui/Instance" ;
3- import { ChildNode , ContainerBase , ContainerConfig } from "../ui/Container" ;
4- import { ControllerProp , VDOM } from "../ui/Widget" ;
3+ import { Prop } from "../ui/Prop" ;
54import type { RenderingContext } from "../ui/RenderingContext" ;
5+ import { VDOM , Widget } from "../ui/Widget" ;
6+ import { isFunction , isNonEmptyArray } from "../util" ;
67import { isArray } from "../util/isArray" ;
7- import { Prop } from "../ui/Prop" ;
8- import { TransformHtmlElementProps } from "./HtmlElement" ;
98
10- // CxJS callback type - can be string (controller method) or callback with Instance as this
11- type CxCallback < T > = T extends ( ...args : infer A ) => infer R
12- ? string | ( ( this : Instance , ...args : A ) => R )
13- : string | T ;
9+ type ReactElementWrapperConfigBase = Omit < ContainerConfig , "items" > ;
1410
15- // Required keys in T
16- type RequiredKeys < T > = {
17- [ K in keyof T ] -?: { } extends Pick < T , K > ? never : K ;
18- } [ keyof T ] ;
19-
20- // Optional keys in T
21- type OptionalKeys < T > = {
22- [ K in keyof T ] -?: { } extends Pick < T , K > ? K : never ;
23- } [ keyof T ] ;
11+ // CxJS callback type - can be string (controller method) or callback with Instance as this
12+ type CxCallback < T > = T extends ( ...args : infer A ) => infer R ? ( this : Instance , ...args : A ) => R : T ;
2413
2514// Transform a single prop: functions to CxCallback, data to Prop<T>
26- type TransformProp < K , V > = K extends "controller"
27- ? ControllerProp
28- : K extends "children"
29- ? ChildNode | ChildNode [ ]
30- : NonNullable < V > extends Function
31- ? CxCallback < V >
32- : Prop < V > ;
15+ type TransformProp < K , V > = K extends keyof ReactElementWrapperConfigBase
16+ ? ReactElementWrapperConfigBase [ K ]
17+ : NonNullable < V > extends Function
18+ ? CxCallback < V >
19+ : Prop < V > ;
3320
3421// Transform React component props - functions to CxCallback, data props to Prop<T>
3522// Preserves required/optional status
36- export type TransformReactElementProps < T > = {
23+ type TransformReactElementProps < T > = {
3724 [ K in keyof T ] : TransformProp < K , T [ K ] > ;
3825} ;
3926
4027/** ReactElementWrapper configuration with component-specific props */
4128// componentType is not included here - it's added by the jsx-runtime and declared in the class
42- export type ReactElementWrapperConfig < P > = ContainerConfig & TransformReactElementProps < P > ;
29+ export type ReactElementWrapperConfig < P > = ReactElementWrapperConfigBase & TransformReactElementProps < P > ;
30+
31+ interface ReactElementWrapperInstance extends Instance {
32+ events ?: Record < string , Function > ;
33+ }
4334
4435export class ReactElementWrapper < C extends React . ComponentType < any > = React . ComponentType < any > > extends ContainerBase <
45- ContainerConfig & { componentType : C }
36+ ReactElementWrapperConfigBase & { componentType : C ; jsxAttributes ?: string [ ] } ,
37+ ReactElementWrapperInstance
4638> {
4739 declare public componentType : React . ComponentType < any > ;
4840 declare public jsxAttributes ?: string [ ] ;
@@ -78,6 +70,16 @@ export class ReactElementWrapper<C extends React.ComponentType<any> = React.Comp
7870 super . init ( ) ;
7971 }
8072
73+ public initInstance ( _context : RenderingContext , _instance : ReactElementWrapperInstance ) : void {
74+ let events : Record < string , Function > | undefined ;
75+ if ( ! isNonEmptyArray ( this . jsxAttributes ) ) return ;
76+ events = { } ;
77+ for ( let prop of this . jsxAttributes ) {
78+ let f = this [ prop ] ;
79+ if ( prop . startsWith ( "on" ) && isFunction ( f ) ) events [ prop ] = ( ...args : any [ ] ) => f . apply ( _instance , args ) ;
80+ }
81+ }
82+
8183 declareData ( ...args : Record < string , unknown > [ ] ) : void {
8284 super . declareData (
8385 {
@@ -87,7 +89,7 @@ export class ReactElementWrapper<C extends React.ComponentType<any> = React.Comp
8789 ) ;
8890 }
8991
90- render ( context : RenderingContext , instance : Instance , key : string ) : React . ReactNode {
92+ render ( context : RenderingContext , instance : ReactElementWrapperInstance , key : string ) : React . ReactNode {
9193 const { data } = instance ;
9294
9395 // Render CxJS children to React elements
@@ -97,6 +99,7 @@ export class ReactElementWrapper<C extends React.ComponentType<any> = React.Comp
9799 const props = {
98100 key,
99101 ...data . props ,
102+ ...instance . events ,
100103 children,
101104 } ;
102105
0 commit comments