Skip to content

Commit b15e8d3

Browse files
committed
fix: better typings / naming
1 parent c5f9337 commit b15e8d3

File tree

6 files changed

+2977
-219
lines changed

6 files changed

+2977
-219
lines changed

.vscode/extensions.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

lib/components/field.ts

Lines changed: 80 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,40 @@ import '@shoelace-style/shoelace/dist/components/range/range.js';
2222
import '@shoelace-style/shoelace/dist/components/switch/switch.js';
2323
import '@shoelace-style/shoelace/dist/components/color-picker/color-picker.js';
2424

25-
import type { Jsf, Path, UiOptions } from '../json-schema-form.js';
25+
import type { Jsf, Path, UiSchema } from '../json-schema-form.js';
2626

2727
export const field = (
2828
schema: JSONSchema7,
2929
value: any,
3030
path: Path,
31-
uiOptions: UiOptions,
31+
uiOptions: UiSchema,
3232
required: boolean,
3333
handleChange: Jsf['_handleChange'],
3434
) => {
35-
const label = schema.title
36-
? schema.title
37-
: isNaN(Number(path.at(-1)))
38-
? path.at(-1)
39-
: undefined;
35+
let label: string | undefined;
36+
37+
if (schema.title) label = schema.title;
38+
else if (Number.isNaN(Number(path.at(-1)))) {
39+
label = path.at(-1);
40+
}
4041

4142
const helpText = schema.description ?? uiOptions?.['ui:help'];
4243
const placeholder = uiOptions?.['ui:placeholder'];
4344

45+
let baseValue: string | number | boolean | undefined;
46+
47+
if (value) {
48+
baseValue = value;
49+
} else if (
50+
schema.default &&
51+
(typeof schema.default === 'string' ||
52+
typeof schema.default === 'number' ||
53+
schema.default == null ||
54+
typeof schema.default === 'boolean')
55+
) {
56+
baseValue = schema.default;
57+
}
58+
4459
if (
4560
schema.type === 'array' &&
4661
typeof schema.items === 'object' &&
@@ -57,7 +72,7 @@ export const field = (
5772
${schema.items.enum.map(
5873
(stringEnum, _index) =>
5974
html` <sl-checkbox
60-
.checked=${value?.includes(stringEnum)}
75+
.checked=${baseValue?.includes(stringEnum)}
6176
@sl-change=${(event: CustomEvent) => {
6277
const { checked } = event.target as SlCheckbox;
6378
@@ -69,15 +84,15 @@ export const field = (
6984
7085
const newData: any[] = [];
7186
72-
value?.map((val: any) => {
73-
if (val === stringEnum && !checked) {
87+
baseValue?.map((newValue: any) => {
88+
if (newValue === stringEnum && !checked) {
7489
} else {
75-
newData.push(val);
90+
newData.push(newValue);
7691
}
7792
});
78-
schema.items.enum?.forEach((val) => {
79-
if (val === stringEnum && checked) {
80-
newData.push(val);
93+
schema.items.enum?.forEach((newValue) => {
94+
if (newValue === stringEnum && checked) {
95+
newData.push(newValue);
8196
}
8297
});
8398
@@ -101,21 +116,22 @@ export const field = (
101116
size="medium"
102117
.label=${label ?? ''}
103118
.helpText=${helpText ?? ''}
104-
value=${ifDefined((schema.default ?? value) || undefined)}
119+
value=${baseValue ? String(baseValue) : ''}
105120
.name=${path.join('.')}
106121
.required=${required}
107122
@sl-change=${(event: CustomEvent) => {
108-
let value: number | string | null = (event.target as SlRadioGroup)
109-
.value;
123+
let newValue: number | string | null = (
124+
event.target as SlRadioGroup
125+
).value;
110126
111127
if (schema.type?.includes('number')) {
112-
value = Number((event.target as HTMLInputElement).value);
128+
newValue = Number((event.target as HTMLInputElement).value);
113129
}
114-
if (schema.type?.[1] === 'null' && !value) {
115-
value = null;
130+
if (schema.type?.[1] === 'null' && !newValue) {
131+
newValue = null;
116132
}
117133
118-
handleChange(path, value);
134+
handleChange(path, newValue);
119135
}}
120136
>
121137
${schema.enum?.map(
@@ -133,28 +149,31 @@ export const field = (
133149
return html`
134150
<sl-select
135151
.label=${label ?? ''}
136-
value=${schema.default ?? value}
152+
value=${baseValue ? String(baseValue) : ''}
137153
.helpText=${helpText ?? ''}
138154
@sl-change=${(event: Event) => {
139-
let value: string | null | number | string[] = (
155+
let newValue: string | null | number | string[] = (
140156
event.target as SlSelect
141157
).value;
142158
143159
if (
144160
schema.type?.includes('number') ||
145161
schema.type?.includes('integer')
146162
) {
147-
value = Number(value);
163+
newValue = Number(newValue);
148164
}
149-
if (schema.type?.[1] === 'null' && !value) {
150-
value = null;
165+
if (schema.type?.[1] === 'null' && !newValue) {
166+
newValue = null;
151167
}
152168
153-
handleChange(path, value);
169+
handleChange(path, newValue);
154170
}}
155171
>
156172
${schema.enum.map(
157-
(val) => html` <sl-option .value=${String(val)}> ${val} </sl-option>`,
173+
(enumValue) =>
174+
html` <sl-option .value=${String(enumValue)}>
175+
${enumValue}
176+
</sl-option>`,
158177
)}
159178
</sl-select>
160179
`;
@@ -191,38 +210,24 @@ export const field = (
191210
step = 1;
192211
}
193212

194-
let val: string | number | boolean | undefined;
195-
196-
if (value) {
197-
val = String(value);
198-
} else if (
199-
schema.default &&
200-
(typeof schema.default === 'string' ||
201-
typeof schema.default === 'number' ||
202-
schema.default == null ||
203-
typeof schema.default === 'boolean')
204-
) {
205-
val = schema.default;
206-
}
207-
208213
if (uiOptions?.['ui:widget'] === 'textarea') {
209214
return html` <sl-textarea
210215
.label=${label ?? ''}
211216
.helpText=${helpText ?? ''}
212217
placeholder=${placeholder ?? ''}
213-
value=${ifDefined(value ? String(value) : undefined)}
218+
value=${baseValue ? String(baseValue) : ''}
214219
.name=${path.join('.')}
215220
.id=${path.join('.')}
216221
.required=${required}
217222
@sl-change=${(event: CustomEvent) => {
218-
let value: null | string = (event.target as HTMLTextAreaElement)
223+
let newValue: null | string = (event.target as HTMLTextAreaElement)
219224
.value;
220225
221-
if (schema.type?.[1] === 'null' && !value) {
222-
value = null;
226+
if (schema.type?.[1] === 'null' && !newValue) {
227+
newValue = null;
223228
}
224229
225-
handleChange(path, value);
230+
handleChange(path, newValue);
226231
}}
227232
></sl-textarea>`;
228233
}
@@ -232,16 +237,16 @@ export const field = (
232237
<label>${label}</label>
233238
<sl-color-picker
234239
.label=${label ?? ''}
235-
value=${ifDefined(String(val))}
240+
value=${baseValue ? String(baseValue) : ''}
236241
@sl-change=${(event: CustomEvent) => {
237-
let value: string | null =
242+
let newValue: string | null =
238243
(event.target as HTMLInputElement).value ?? schema.default;
239244
240-
if (schema.type?.[1] === 'null' && !value) {
241-
value = null;
245+
if (schema.type?.[1] === 'null' && !newValue) {
246+
newValue = null;
242247
}
243248
244-
handleChange(path, value);
249+
handleChange(path, newValue);
245250
}}
246251
></sl-color-picker>
247252
@@ -255,18 +260,18 @@ export const field = (
255260
<sl-range
256261
.label=${label ?? ''}
257262
.helpText=${helpText ?? ''}
258-
value=${ifDefined(val ? Number(val) : undefined)}
263+
value=${ifDefined(baseValue ? Number(baseValue) : undefined)}
259264
.type=${type}
260265
step=${ifDefined(step)}
261266
min=${ifDefined(schema.minimum)}
262267
max=${ifDefined(schema.maximum)}
263268
.name=${path.join('.')}
264269
.required=${required}
265270
@sl-change=${(event: CustomEvent) => {
266-
let { value } = event.target as SlRange;
271+
const { value: newValue } = event.target as SlRange;
267272
268-
let val: number | null | undefined = value;
269-
if (schema.type?.[1] === 'null' && !value) {
273+
let val: number | null | undefined = newValue;
274+
if (schema.type?.[1] === 'null' && !newValue) {
270275
val = null;
271276
}
272277
@@ -284,7 +289,7 @@ export const field = (
284289
.type=${type}
285290
.helpText=${helpText ?? ''}
286291
placeholder=${placeholder ?? ''}
287-
value=${ifDefined(val)}
292+
value=${ifDefined(baseValue)}
288293
.name=${path.join('.')}
289294
.id=${path.join('.')}
290295
.required=${required}
@@ -295,16 +300,19 @@ export const field = (
295300
maxLength=${ifDefined(schema.maxLength)}
296301
pattern=${ifDefined(schema.pattern)}
297302
@sl-change=${(event: CustomEvent) => {
298-
let { value, type, valueAsNumber } =
299-
event.target as HTMLInputElement;
300-
301-
let val: number | string | null | undefined = value;
302-
if (type === 'number') {
303+
const {
304+
value: newValue,
305+
type: inputType,
306+
valueAsNumber,
307+
} = event.target as HTMLInputElement;
308+
309+
let val: number | string | null | undefined = newValue;
310+
if (inputType === 'number') {
303311
val = valueAsNumber;
304312
}
305313
if (
306314
schema.type?.[1] === 'null' &&
307-
(typeof value === 'undefined' || value === '')
315+
(typeof newValue === 'undefined' || newValue === '')
308316
) {
309317
val = null;
310318
}
@@ -335,21 +343,15 @@ export const field = (
335343
size="medium"
336344
.label=${label ?? ''}
337345
.helpText=${helpText ?? ''}
338-
value=${ifDefined(
339-
typeof schema.default !== undefined
340-
? String(schema.default)
341-
: typeof value !== undefined
342-
? String(value)
343-
: undefined,
344-
)}
346+
value=${ifDefined(baseValue ? String(baseValue) : '')}
345347
.name=${path.join('.')}
346348
.required=${required}
347349
@sl-change=${(event: CustomEvent) => {
348-
let { value } = event.target as HTMLInputElement;
350+
const { value: newValue } = event.target as HTMLInputElement;
349351
350352
let val: boolean | null | undefined;
351-
val = value === 'true';
352-
if (schema.type?.[1] === 'null' && !value) {
353+
val = newValue === 'true';
354+
if (schema.type?.[1] === 'null' && !newValue) {
353355
val = null;
354356
}
355357
@@ -369,12 +371,12 @@ export const field = (
369371
return html`
370372
<div>
371373
<sl-switch
372-
.checked=${schema.default ?? value}
374+
.checked=${Boolean(baseValue)}
373375
.name=${path.join('.')}
374376
@sl-change=${(event: CustomEvent) => {
375-
const value = (event.target as SlSwitch).checked;
377+
const newValue = (event.target as SlSwitch).checked;
376378
377-
handleChange(path, value);
379+
handleChange(path, newValue);
378380
}}
379381
>${label}</sl-switch
380382
>
@@ -387,9 +389,9 @@ export const field = (
387389
.checked=${schema.default ?? value}
388390
.name=${path.join('.')}
389391
@sl-change=${(event: CustomEvent) => {
390-
const value = (event.target as SlCheckbox).checked;
392+
const newValue = (event.target as SlCheckbox).checked;
391393
392-
handleChange(path, value);
394+
handleChange(path, newValue);
393395
}}
394396
>${label}</sl-checkbox
395397
>

lib/json-schema-form.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable class-methods-use-this */
12
/* eslint-disable no-underscore-dangle */
23
/* eslint-disable arrow-body-style */
34
/* eslint-disable max-lines */
@@ -20,21 +21,21 @@ import styles from './styles.js';
2021

2122
export type Path = string[];
2223

23-
export type UiOptions = {
24-
'ui:help'?: string;
25-
'ui:placeholder'?: string;
26-
27-
'ui:widget'?:
28-
| 'radio'
29-
| 'button-group'
30-
| 'textarea'
31-
| 'color'
32-
| 'range'
33-
| 'password'
34-
| 'switch';
35-
};
36-
37-
export type UiSchema = UiOptions & { [key: string]: UiSchema }; // Record<string, UiOptions>;
24+
export type UiSchema =
25+
| {
26+
'ui:help'?: string;
27+
'ui:placeholder'?: string;
28+
29+
'ui:widget'?:
30+
| 'radio'
31+
| 'button-group'
32+
| 'textarea'
33+
| 'color'
34+
| 'range'
35+
| 'password'
36+
| 'switch';
37+
}
38+
| { [key: string]: UiSchema };
3839

3940
export interface FeatureFlags {
4041
allOf?: boolean;

lib/styles.scss

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,12 @@
1212

1313
fieldset {
1414
display: flex;
15-
1615
flex-direction: column;
17-
1816
gap: var(--sl-spacing-large);
19-
2017
padding: var(--sl-spacing-large) var(--sl-spacing-medium);
2118
margin: 0;
2219
font-weight: var(--sl-font-weight-semibold);
23-
border: 1px solid var(--sl-color-neutral-0);
20+
border: 1px solid var(--sl-color-neutral-50);
2421
border-radius: var(--sl-border-radius-large);
2522

2623
legend {
@@ -51,6 +48,7 @@ fieldset {
5148
align-items: center;
5249
justify-content: space-between;
5350
width: 100%;
51+
5452
sl-tag::part(base) {
5553
background: var(--sl-color-neutral-0);
5654
}

0 commit comments

Comments
 (0)