@@ -11,6 +11,7 @@ import Handlebars from 'handlebars';
1111import * as Utils from '../../../scripts/web-component-wrappers/utils.js' ;
1212import {
1313 COMPONENTS_WITHOUT_DEMOS ,
14+ KNOWN_ATTRIBUTES ,
1415 KNOWN_EVENTS ,
1516 PRIVATE_COMPONENTS
1617} from '../../../scripts/web-component-wrappers/config.js' ;
@@ -291,58 +292,72 @@ const getEventParameters = (name, parameters) => {
291292} ;
292293
293294const createWebComponentWrapper = async (
294- name ,
295- tag ,
295+ componentSpec ,
296296 description ,
297- types ,
297+ attributes ,
298+ slotsAndEvents ,
298299 importStatements ,
299- ref ,
300300 defaultProps ,
301301 regularProps ,
302302 booleanProps ,
303303 slotProps ,
304304 eventProps
305305) => {
306- const eventsToBeOmitted = eventProps . filter ( ( eventName ) => KNOWN_EVENTS . has ( eventName ) ) ;
306+ const eventsToBeOmitted = eventProps
307+ . filter ( ( eventName ) => KNOWN_EVENTS . has ( eventName ) )
308+ . map ( ( eventName ) => `'on${ capitalizeFirstLetter ( snakeToCamel ( eventName ) ) } '` ) ;
309+ const attributesToBeOmitted = [ ...regularProps , ...booleanProps ]
310+ . filter ( ( attribute ) => KNOWN_ATTRIBUTES . has ( attribute ) )
311+ . map ( ( a ) => `'${ a } '` ) ;
312+
313+ let domRefExtends = 'Ui5DomRef' ;
314+ if ( attributesToBeOmitted . length > 0 ) {
315+ domRefExtends = `Omit<Ui5DomRef, ${ attributesToBeOmitted . join ( ' | ' ) } >` ;
316+ }
317+
307318 let tsExtendsStatement = 'CommonProps' ;
308- if ( eventsToBeOmitted . length > 0 ) {
309- tsExtendsStatement = `Omit<CommonProps, ${ eventsToBeOmitted
310- . map ( ( eventName ) => `'on${ capitalizeFirstLetter ( snakeToCamel ( eventName ) ) } '` )
311- . join ( ' | ' ) } >`;
319+ if ( eventsToBeOmitted . length > 0 || attributesToBeOmitted . length > 0 ) {
320+ tsExtendsStatement = `Omit<CommonProps, ${ [ ...attributesToBeOmitted , ...eventsToBeOmitted ] . join ( ' | ' ) } >` ;
312321 }
313322 let componentDescription ;
314323 try {
315324 componentDescription = turndownService . turndown ( description ) . replace ( / \n / g, '\n * ' ) ;
316325 } catch ( e ) {
317326 console . warn (
318- `----------------------\nHeader description of ${ name } couldn't be generated. \nThere is probably a syntax error in the associated description that can't be fixed automatically.\n----------------------`
327+ `----------------------\nHeader description of ${ componentSpec . module } couldn't be generated. \nThere is probably a syntax error in the associated description that can't be fixed automatically.\n----------------------`
319328 ) ;
320329 componentDescription = '' ;
321330 }
322331
332+ const domRef = Utils . createDomRef ( componentSpec ) ;
333+
323334 const imports = [
324335 ...importStatements ,
325336 '' , // do not remove this empty line - otherwise the eslint/import-order plugin won't work as expected
326- `import '@ui5/webcomponents${ componentsFromFioriPackage . has ( name ) ? '-fiori' : '' } /dist/${ name } .js';`
337+ `import '@ui5/webcomponents${ componentsFromFioriPackage . has ( componentSpec . module ) ? '-fiori' : '' } /dist/${
338+ componentSpec . module
339+ } .js';`
327340 ] ;
328341
329342 return prettier . format (
330343 await Utils . runEsLint (
331344 componentTemplate ( {
332- name,
345+ name : componentSpec . module ,
333346 imports,
334347 propTypesExtends : tsExtendsStatement ,
335- types,
348+ domRefExtends,
349+ attributes,
350+ slotsAndEvents,
336351 description : componentDescription ,
337- tagName : tag ,
352+ tagName : componentSpec . tagname ,
338353 regularProps,
339354 booleanProps,
340355 slotProps : slotProps . filter ( ( name ) => name !== 'children' ) ,
341356 eventProps,
342357 defaultProps,
343- ref : ref ?. tsType
358+ domRef
344359 } ) ,
345- name
360+ componentSpec . module
346361 ) ,
347362 Utils . prettierConfig
348363 ) ;
@@ -570,59 +585,55 @@ const resolveInheritedAttributes = (componentSpec) => {
570585 ) ;
571586} ) ;
572587
588+ const propDescription = ( componentSpec , property ) => {
589+ if ( ! componentSpec . tagname ) {
590+ return property . description || '' ;
591+ }
592+ let formattedDescription = turndownService . turndown ( ( property . description || '' ) . trim ( ) ) . replace ( / \n / g, '\n * ' ) ;
593+
594+ const customDescriptionReplace = CUSTOM_DESCRIPTION_REPLACE [ componentSpec . module ] ;
595+ if ( customDescriptionReplace && customDescriptionReplace [ property . name ] ) {
596+ formattedDescription = customDescriptionReplace [ property . name ] ( formattedDescription ) ;
597+ }
598+
599+ const extendedDescription = EXTENDED_PROP_DESCRIPTION [ property . name ] ;
600+
601+ if ( property . name !== 'children' && componentSpec ?. slots ?. some ( ( item ) => item . name === property . name ) ) {
602+ formattedDescription += `
603+ *
604+ * __Note:__ When passing a custom React component to this prop, you have to make sure your component reads the \`slot\` prop and appends it to the most outer element of your component.
605+ * Learn more about it [here](https://sap.github.io/ui5-webcomponents-react/?path=/docs/knowledge-base--page#adding-custom-components-to-slots).` ;
606+ }
607+
608+ if ( extendedDescription ) {
609+ return replaceTagNameWithModuleName ( `${ formattedDescription } ${ extendedDescription } ` ) ;
610+ }
611+ return replaceTagNameWithModuleName ( formattedDescription ) ;
612+ } ;
613+
573614allWebComponents
574615 . filter ( ( spec ) => spec . visibility === 'public' )
575616 . filter ( ( spec ) => ! PRIVATE_COMPONENTS . has ( spec . module ) )
576617 . map ( resolveInheritedAttributes )
577618 . forEach ( async ( componentSpec ) => {
578- const propTypes = [ ] ;
619+ const attributes = [ ] ;
620+ const slotsAndEvents = [ ] ;
579621 const importStatements = [ ] ;
580622 const defaultProps = [ ] ;
581- const allComponentProperties = [ ... ( componentSpec . properties || [ ] ) , ... ( componentSpec . slots || [ ] ) ]
623+ const allComponentProperties = ( componentSpec . properties || [ ] )
582624 . filter ( ( prop ) => prop . visibility === 'public' && prop . readonly !== 'true' && prop . static !== true )
583625 . map ( ( property ) => {
584626 const tsType = Utils . getTypeDefinitionForProperty ( property ) ;
585627 if ( tsType . importStatement ) {
586628 importStatements . push ( tsType . importStatement ) ;
587629 }
588630
589- if ( property . name === 'default' ) {
590- property . name = 'children' ;
591- }
592- const propDescription = ( ) => {
593- if ( ! componentSpec . tagname ) {
594- return property . description || '' ;
595- }
596- let formattedDescription = turndownService
597- . turndown ( ( property . description || '' ) . trim ( ) )
598- . replace ( / \n / g, '\n * ' ) ;
599-
600- const customDescriptionReplace = CUSTOM_DESCRIPTION_REPLACE [ componentSpec . module ] ;
601- if ( customDescriptionReplace && customDescriptionReplace [ property . name ] ) {
602- formattedDescription = customDescriptionReplace [ property . name ] ( formattedDescription ) ;
603- }
604-
605- const extendedDescription = EXTENDED_PROP_DESCRIPTION [ property . name ] ;
606-
607- if ( property . name !== 'children' && componentSpec ?. slots ?. some ( ( item ) => item . name === property . name ) ) {
608- formattedDescription += `
609- *
610- * __Note:__ When passing a custom React component to this prop, you have to make sure your component reads the \`slot\` prop and appends it to the most outer element of your component.
611- * Learn more about it [here](https://sap.github.io/ui5-webcomponents-react/?path=/docs/knowledge-base--page#adding-custom-components-to-slots).` ;
612- }
613-
614- if ( extendedDescription ) {
615- return replaceTagNameWithModuleName ( `${ formattedDescription } ${ extendedDescription } ` ) ;
616- }
617- return replaceTagNameWithModuleName ( formattedDescription ) ;
618- } ;
619-
620- propTypes . push ( dedent `
621- /**
622- * ${ propDescription ( ) }
623- */
624- ${ property . name } ?: ${ tsType . tsType } ;
625- ` ) ;
631+ attributes . push ( dedent `
632+ /**
633+ * ${ propDescription ( componentSpec , property ) }
634+ */
635+ ${ property . name } ?: ${ tsType . tsType } ;
636+ ` ) ;
626637
627638 if (
628639 property . hasOwnProperty ( 'defaultValue' ) &&
@@ -646,6 +657,33 @@ allWebComponents
646657 } ;
647658 } ) ;
648659
660+ allComponentProperties . push (
661+ ...( componentSpec . slots || [ ] )
662+ . filter ( ( prop ) => prop . visibility === 'public' && prop . readonly !== 'true' && prop . static !== true )
663+ . map ( ( property ) => {
664+ const tsType = Utils . getTypeDefinitionForProperty ( property ) ;
665+ if ( tsType . importStatement ) {
666+ importStatements . push ( tsType . importStatement ) ;
667+ }
668+
669+ if ( property . name === 'default' ) {
670+ property . name = 'children' ;
671+ }
672+
673+ slotsAndEvents . push ( dedent `
674+ /**
675+ * ${ propDescription ( componentSpec , property ) }
676+ */
677+ ${ property . name } ?: ${ tsType . tsType } ;
678+ ` ) ;
679+
680+ return {
681+ ...property ,
682+ ...tsType
683+ } ;
684+ } )
685+ ) ;
686+
649687 ( componentSpec . events || [ ] )
650688 . filter ( ( eventSpec ) => eventSpec . visibility === 'public' )
651689 . forEach ( ( eventSpec ) => {
@@ -666,7 +704,7 @@ allWebComponents
666704 eventParameters = getEventParameters ( componentSpec . module , eventSpec . parameters || [ ] ) ;
667705 }
668706 importStatements . push ( ...eventParameters . importStatements ) ;
669- propTypes . push ( dedent `
707+ slotsAndEvents . push ( dedent `
670708 /**
671709 * ${ replaceTagNameWithModuleName (
672710 turndownService . turndown ( ( eventSpec . description || '' ) . trim ( ) ) . replace ( / \n / g, '\n * ' )
@@ -676,8 +714,6 @@ allWebComponents
676714 ` ) ;
677715 } ) ;
678716
679- const uniqueAdditionalImports = [ ...new Set ( importStatements ) ] ;
680-
681717 const formatDescription = ( ) => {
682718 let description = componentSpec . description ;
683719 if ( ! description ) {
@@ -718,22 +754,16 @@ allWebComponents
718754 fs . writeFileSync ( webComponentWrapperPath , '' ) ;
719755 }
720756
721- const domRef = Utils . createDomRef ( componentSpec ) ;
722- if ( domRef ) {
723- uniqueAdditionalImports . push ( domRef . importStatement ) ;
724- }
725-
726757 if (
727758 ( CREATE_SINGLE_COMPONENT === componentSpec . module || ! CREATE_SINGLE_COMPONENT ) &&
728759 ! EXCLUDE_LIST . includes ( componentSpec . module )
729760 ) {
730761 const webComponentWrapper = await createWebComponentWrapper (
731- componentSpec . module ,
732- componentSpec . tagname ,
762+ componentSpec ,
733763 mainDescription ,
734- propTypes ,
735- uniqueAdditionalImports ,
736- domRef ,
764+ attributes ,
765+ slotsAndEvents ,
766+ [ ... new Set ( importStatements ) ] ,
737767 defaultProps ,
738768 ( componentSpec . properties || [ ] )
739769 . filter ( filterNonPublicAttributes )
0 commit comments