@@ -12,11 +12,23 @@ import { ifDefined } from 'lit/directives/if-defined.js';
1212
1313type KnobRenderer < T > = (
1414 this : PftElementKnobs < HTMLElement > ,
15- attribute : T ,
16- index : number ,
17- array : T [ ] ,
15+ member : T ,
16+ info : T extends Attribute ? AttributeKnobInfo : KnobInfo ,
1817) => unknown ;
1918
19+ interface KnobInfo {
20+ knobId : string ;
21+ }
22+
23+ interface AttributeKnobInfo extends KnobInfo {
24+ isBoolean : boolean ;
25+ isEnum : boolean ;
26+ isNullable : boolean ;
27+ isNumber : boolean ;
28+ isOptional : boolean ;
29+ values : string [ ] ;
30+ }
31+
2032export type AttributeRenderer = KnobRenderer < Attribute > ;
2133
2234const isCustomElementDecl = ( decl : Declaration ) : decl is CustomElementDeclaration =>
@@ -89,37 +101,46 @@ export class PftElementKnobs<T extends HTMLElement> extends LitElement {
89101 }
90102 }
91103
92- #renderAttribute( attribute : Attribute ) {
104+ #getAttributeInfo( attribute : Attribute ) : AttributeKnobInfo {
105+ // NOTE: we assume typescript types
106+ const type = attribute ?. type ?. text ?? '' ;
107+ const isUnion = ! ! type . includes ?.( '|' ) ;
108+ const types = type . split ( '|' ) . map ( x => x . trim ( ) ) ;
109+ const isNullable = types . includes ( 'null' ) ;
110+ const isOptional = types . includes ( 'undefined' ) ;
111+ const isNumber = types . includes ( 'number' ) ;
112+ const isBoolean = types . every ( type => type . match ( / n u l l | u n d e f i n e d | b o o l e a n / ) ) ;
113+ const values = isUnion ? types . filter ( x => x !== 'undefined' && x !== 'null' ) : [ ] ;
114+ const isEnum = isUnion && values . length > 1 ;
115+ const knobId = `knob-attribute-${ attribute . name } ` ;
116+ return {
117+ knobId,
118+ isBoolean,
119+ isEnum,
120+ isNullable,
121+ isNumber,
122+ isOptional,
123+ values,
124+ } ;
125+ }
126+
127+ #renderAttribute( attribute : Attribute , info : AttributeKnobInfo ) {
128+ const { knobId, isEnum, isBoolean, values } = info ;
93129 const QUOTE_RE = / ^ [ ' " ] ( .* ) [ ' " ] $ / ;
94- // TODO: non-typescript types?
95- const isBoolean = attribute ?. type ?. text === 'boolean' ;
96- const isUnion = ! ! attribute ?. type ?. text ?. includes ?.( '|' ) ;
97- let isEnum = false ;
98- let values : string [ ] ;
99- if ( isUnion ) {
100- values = attribute ?. type ?. text
101- . split ( '|' )
102- . map ( x => x . trim ( ) )
103- . filter ( x => x !== 'undefined' && x !== 'null' ) ?? [ ] ;
104- if ( values . length > 1 ) {
105- isEnum = true ;
106- }
107- }
108- const id = `knob-attribute-${ attribute . name } ` ;
109130 return html `
110- < label for ="${ id } "> ${ attribute . name } </ label > ${ isBoolean ? html `
111- < input id ="${ id } "
131+ < label for ="${ knobId } "> ${ attribute . name } </ label > ${ isBoolean ? html `
132+ < input id ="${ knobId } "
112133 type ="checkbox "
113134 ?checked ="${ attribute . default === 'true' } "
114135 data-attribute ="${ attribute . name } "> ` : isEnum ? html `
115- < pf-select id ="${ id } "
136+ < pf-select id ="${ knobId } "
116137 placeholder ="Select a value "
117138 data-attribute ="${ attribute . name } "
118139 value ="${ ifDefined ( attribute . default ?. replace ( QUOTE_RE , '$1' ) ) } "> ${ values ! . map ( x => html `
119140 < pf-option > ${ x . trim ( ) . replace ( QUOTE_RE , '$1' ) } </ pf-option > ` ) }
120141 </ pf-select >
121142 ` : html `
122- < pf-text-input id ="${ id } "
143+ < pf-text-input id ="${ knobId } "
123144 value ="${ ifDefined ( attribute . default ?. replace ( QUOTE_RE , '$1' ) ) } "
124145 helper-text ="${ ifDefined ( attribute . type ?. text ) } "
125146 data-attribute ="${ attribute . name } "> </ pf-text-input > ` }
@@ -145,7 +166,7 @@ export class PftElementKnobs<T extends HTMLElement> extends LitElement {
145166 ${ ! attributes ? '' : html `
146167 < fieldset @change ="${ onChange } " @input ="${ onChange } ">
147168 < legend > Attributes</ legend >
148- ${ attributes . map ( this . renderAttribute , this ) }
169+ ${ attributes . map ( attr => this . renderAttribute ( attr , this . #getAttributeInfo ( attr ) ) ) }
149170 </ fieldset > ` }
150171 </ form >
151172 ` ;
0 commit comments