Skip to content

Commit 05e5dde

Browse files
committed
refactor: attribute renderer
1 parent 82e1c7c commit 05e5dde

File tree

1 file changed

+45
-24
lines changed

1 file changed

+45
-24
lines changed

tools/pfe-tools/elements/pft-element-knobs.ts

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,23 @@ import { ifDefined } from 'lit/directives/if-defined.js';
1212

1313
type 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+
2032
export type AttributeRenderer = KnobRenderer<Attribute>;
2133

2234
const 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(/null|undefined|boolean/));
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

Comments
 (0)