3
3
import { getEffectiveScopingSuffixForTag } from '@ui5/webcomponents-base/dist/CustomElementsScope.js' ;
4
4
import { useIsomorphicLayoutEffect , useSyncRef } from '@ui5/webcomponents-react-base' ;
5
5
import type { ComponentType , ReactElement , ReactNode , Ref } from 'react' ;
6
- import { cloneElement , forwardRef , Fragment , isValidElement , useEffect , useState } from 'react' ;
6
+ import { cloneElement , forwardRef , Fragment , isValidElement , useEffect , useState , version } from 'react' ;
7
7
import type { CommonProps , Ui5DomRef } from '../types/index.js' ;
8
8
import { useServerSideEffect } from './ssr.js' ;
9
9
import { camelToKebabCase , capitalizeFirstLetter , kebabToCamelCase } from './utils.js' ;
10
10
11
+ const SEMVER_REGEX =
12
+ / ^ (?< major > 0 | [ 1 - 9 ] \d * ) \. (?< minor > 0 | [ 1 - 9 ] \d * ) \. (?< patch > 0 | [ 1 - 9 ] \d * ) (?: - (?< prerelease > (?: 0 | [ 1 - 9 ] \d * | \d * [ a - z A - Z - ] [ 0 - 9 a - z A - Z - ] * ) (?: \. (?: 0 | [ 1 - 9 ] \d * | \d * [ a - z A - Z - ] [ 0 - 9 a - z A - Z - ] * ) ) * ) ) ? (?: \+ (?< buildmetadata > [ 0 - 9 a - z A - Z - ] + (?: \. [ 0 - 9 a - z A - Z - ] + ) * ) ) ? $ / ;
13
+
11
14
const createEventPropName = ( eventName : string ) => `on${ capitalizeFirstLetter ( kebabToCamelCase ( eventName ) ) } ` ;
12
15
13
16
const isPrimitiveAttribute = ( value : unknown ) : boolean => {
@@ -35,6 +38,8 @@ export const withWebComponent = <Props extends Record<string, any>, RefType = Ui
35
38
eventProperties : string [ ] ,
36
39
loader : ( ) => Promise < unknown >
37
40
) => {
41
+ const reactMajorVersion = SEMVER_REGEX . exec ( version ) ?. groups ?. major ;
42
+ const webComponentsSupported = parseInt ( reactMajorVersion ) >= 19 ;
38
43
// displayName will be assigned in the individual files
39
44
// eslint-disable-next-line react/display-name
40
45
return forwardRef < RefType , Props & WithWebComponentPropTypes > ( ( props , wcRef ) => {
@@ -61,10 +66,14 @@ export const withWebComponent = <Props extends Record<string, any>, RefType = Ui
61
66
62
67
// boolean properties - only attach if they are truthy
63
68
const booleanProps = booleanProperties . reduce ( ( acc , name ) => {
64
- if ( rest [ name ] === true || rest [ name ] === 'true' ) {
65
- return { ...acc , [ camelToKebabCase ( name ) ] : true } ;
69
+ if ( webComponentsSupported ) {
70
+ return { ...acc , [ camelToKebabCase ( name ) ] : rest [ name ] } ;
71
+ } else {
72
+ if ( rest [ name ] === true || rest [ name ] === 'true' ) {
73
+ return { ...acc , [ camelToKebabCase ( name ) ] : true } ;
74
+ }
75
+ return acc ;
66
76
}
67
- return acc ;
68
77
} , { } ) ;
69
78
70
79
const slots = slotProperties . reduce ( ( acc , name ) => {
@@ -119,6 +128,11 @@ export const withWebComponent = <Props extends Record<string, any>, RefType = Ui
119
128
120
129
// event binding
121
130
useIsomorphicLayoutEffect ( ( ) => {
131
+ if ( webComponentsSupported ) {
132
+ return ( ) => {
133
+ // React can handle events
134
+ } ;
135
+ }
122
136
const localRef = ref . current ;
123
137
const eventRegistry : Record < string , EventHandler > = { } ;
124
138
if ( ! waitForDefine || isDefined ) {
@@ -140,6 +154,14 @@ export const withWebComponent = <Props extends Record<string, any>, RefType = Ui
140
154
}
141
155
} , [ ...eventProperties . map ( ( eventName ) => rest [ createEventPropName ( eventName ) ] ) , isDefined , waitForDefine ] ) ;
142
156
157
+ const eventHandlers = eventProperties . reduce ( ( events , eventName ) => {
158
+ const eventHandlerProp = rest [ createEventPropName ( eventName ) ] ;
159
+ if ( webComponentsSupported && eventHandlerProp ) {
160
+ events [ `on${ eventName } ` ] = eventHandlerProp ;
161
+ }
162
+ return events ;
163
+ } , { } ) ;
164
+
143
165
// non web component related props, just pass them
144
166
const nonWebComponentRelatedProps = Object . entries ( rest )
145
167
. filter ( ( [ key ] ) => ! regularProperties . includes ( key ) )
@@ -185,6 +207,7 @@ export const withWebComponent = <Props extends Record<string, any>, RefType = Ui
185
207
ref = { componentRef }
186
208
{ ...booleanProps }
187
209
{ ...regularProps }
210
+ { ...eventHandlers }
188
211
{ ...nonWebComponentRelatedProps }
189
212
class = { className }
190
213
suppressHydrationWarning
0 commit comments