Skip to content

Commit 91145ae

Browse files
fixed types
1 parent 424d28e commit 91145ae

File tree

5 files changed

+58
-233
lines changed

5 files changed

+58
-233
lines changed

index.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
// uniqueItems: true,
2626
// },
2727
schema: await (await fetch("./fixtures/coa-schema.json")).json(),
28-
path: location.hash.replace(/#/i, ""),
28+
// schema: await (await fetch("./fixtures/coa-schema.json")).json(),
29+
path: location.hash.replace(/#/i, "").replaceAll("/", "."),
2930
value: JSON.parse(localStorage.getItem("JSON_UI_VALUE")),
3031
});
3132

src/body-element.ts

+25-217
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
PRIMITIVE_TYPES,
1818
ALL_TYPES,
1919
PATH_UP,
20+
ROOT_PATH,
2021
} from "./constants";
2122
import { inferType } from "./parser/infer";
2223
import { JSONSchema7Value } from "./utils/helper-types";
@@ -67,6 +68,7 @@ export class BodyElement extends LitElement {
6768
render() {
6869
console.debug(`[DEBUG] Rendering body.`);
6970
const itemType = inferType(this.schema!, this.value);
71+
7072
return html`
7173
${choose(
7274
itemType,
@@ -82,17 +84,15 @@ export class BodyElement extends LitElement {
8284
).map(([key, prop]) => [
8385
key,
8486
inferType(prop, this.value?.[key]),
85-
])
87+
]),
88+
false,
89+
this.path === ROOT_PATH
8690
),
8791
],
8892
["array", () => this.renderArray()],
93+
[undefined, () => html``],
8994
],
90-
() =>
91-
when(
92-
PRIMITIVE_TYPES.includes(itemType),
93-
() => this.renderPrimitive(itemType),
94-
() => html`Unknown type <strong>${itemType}</strong>.`
95-
)
95+
() => this.renderProperty()
9696
)}
9797
<div class="h-8"></div>
9898
${when(
@@ -116,9 +116,13 @@ export class BodyElement extends LitElement {
116116
);
117117
}
118118

119-
private renderProperty(key?: string | number, skipHeader = false) {
119+
private renderProperty(key?: string | number, skipRemove = false) {
120120
const value = !isUndefined(key) ? this.value?.[key] : this.value;
121-
const schema = navigateSchema(this.schema!, key) as JSONSchema7;
121+
const schema =
122+
typeof key === "number"
123+
? (this.schema!.items as JSONSchema7)
124+
: (navigateSchema(this.schema!, key) as JSONSchema7);
125+
122126
const itemType = inferType(schema, value);
123127
const title = key ?? schema?.title;
124128
const description = schema?.description;
@@ -135,27 +139,26 @@ export class BodyElement extends LitElement {
135139
() => "error"
136140
)}"
137141
>
138-
${when(!skipHeader && title, () =>
139-
renderLabel(String(title), description, required)
140-
)}
142+
${when(title, () => renderLabel(String(title), description, required))}
141143
${when(
142144
PRIMITIVE_TYPES.includes(itemType),
143-
() => this.renderPrimitive2(itemType, value, schema, key),
145+
() => this.renderPrimitive(itemType, value, schema, key),
144146
() =>
145-
this.renderValuePreview2(
147+
this.renderValuePreview(
146148
itemType,
147149
value,
148150
schema,
149151
key,
150152
required,
151-
valid
153+
valid,
154+
skipRemove
152155
)
153156
)}
154157
</label>
155158
`;
156159
}
157160

158-
private renderPrimitive2(
161+
private renderPrimitive(
159162
type: (typeof PRIMITIVE_TYPES)[number],
160163
value: any,
161164
schema: any,
@@ -206,84 +209,6 @@ export class BodyElement extends LitElement {
206209
);
207210
}
208211

209-
private renderPrimitive(
210-
type: (typeof PRIMITIVE_TYPES)[number],
211-
key?: string | number,
212-
skipHeader = false
213-
) {
214-
const value = !isUndefined(key) ? this.value?.[key] : this.value;
215-
const schema = navigateSchema(this.schema!, key) as JSONSchema7;
216-
const title = schema?.title ?? key;
217-
const description = schema?.description;
218-
const ajv = ajvFactory();
219-
const compiled = ajv.compile(schema);
220-
const valid = compiled(value);
221-
222-
return html`<label
223-
id="#${key}"
224-
class="flex flex-col gap-4 w-full ${when(
225-
!isUndefined(value) && !valid,
226-
() => "error"
227-
)}"
228-
>
229-
${when(!skipHeader && title, () =>
230-
renderLabel(
231-
String(title),
232-
description,
233-
this.required.includes(String(key))
234-
)
235-
)}
236-
${when(
237-
schema?.enum,
238-
() => {
239-
const enumOptions = ((schema?.enum as any[]) ?? []).map((item) =>
240-
String(item)
241-
);
242-
return html`<single-dropdown-element
243-
@change=${dispatchChange(this, String(key ?? ""))}
244-
.options=${enumOptions}
245-
.value=${value}
246-
></single-dropdown-element>`;
247-
},
248-
() =>
249-
choose(type, [
250-
[
251-
"string",
252-
() => html`<string-element
253-
@change=${dispatchChange(this, String(key ?? ""))}
254-
.value=${value}
255-
.schema=${schema}
256-
></string-element>`,
257-
],
258-
[
259-
"number",
260-
() => html`<number-element
261-
@change=${dispatchChange(this, String(key ?? ""))}
262-
.value=${value}
263-
.schema=${schema}
264-
></number-element>`,
265-
],
266-
[
267-
"integer",
268-
() => html`<number-element
269-
@change=${dispatchChange(this, String(key ?? ""))}
270-
.value=${value}
271-
.schema=${schema}
272-
></number-element>`,
273-
],
274-
[
275-
"boolean",
276-
() => html`<checkbox-element
277-
@change=${dispatchChange(this, String(key ?? ""))}
278-
.value=${value}
279-
.label=${humanizeKey(String(key))}
280-
></checkbox-element>`,
281-
],
282-
])
283-
)}
284-
</label>`;
285-
}
286-
287212
private firstInvalidComplexType = (
288213
properties: [key: string, type: (typeof ALL_TYPES)[number]][],
289214
required?: string[]
@@ -358,53 +283,15 @@ export class BodyElement extends LitElement {
358283
`;
359284
};
360285

361-
private renderAdditionalProperties() {
362-
const additionalProperties = this.schema?.[ADDITIONAL_PROPERTIES_KEY];
363-
if (additionalProperties === false) return nothing;
364-
const propertyKeys = Object.keys(
365-
(this.schema?.[PROPERTIES_KEY] as unknown as JSONSchema7Value[]) ?? []
366-
);
367-
const unspecifiedProperties: [
368-
key: string,
369-
type: ReturnType<typeof inferType>
370-
][] = Object.entries(this.value ?? {})
371-
.filter(([key]) => !propertyKeys.includes(key))
372-
.map(([key, value]) => [key, inferType(undefined, value)]);
373-
374-
return html`
375-
${this.renderObject(unspecifiedProperties, true, true, false, false)}
376-
<button-element .iconLeft="${icons.ADD()}"
377-
>Add custom field</button-element
378-
>
379-
`;
380-
}
381-
382-
// itemState
383-
384-
/* Item state:
385-
*
386-
*/
387-
388-
//
389-
390-
// - optional and empty
391-
// - optional and error
392-
// - required
393-
// - required and empty
394-
// - required and error
395-
// - required and filled
396-
// - required and filled and error
397-
398-
private renderValuePreview2(
286+
private renderValuePreview(
399287
type: (typeof PRIMITIVE_TYPES)[number],
400288
value: any,
401289
schema: any,
402290
key?: string | number,
403291
required?: boolean,
404-
valid?: boolean
292+
valid?: boolean,
293+
skipRemove = false
405294
) {
406-
// .state=${valid ? "normal" : "error"}
407-
// .iconLeft=${valid ? void 0 : icons.ERROR()}
408295
return html`
409296
${when(
410297
isUndefined(value) && required,
@@ -433,7 +320,7 @@ export class BodyElement extends LitElement {
433320
</button-element>
434321
435322
${when(
436-
!isUndefined(value),
323+
!isUndefined(value) && !skipRemove,
437324
() => html`<button-element
438325
.icon=${icons.REMOVE()}
439326
@click="${() =>
@@ -453,81 +340,6 @@ export class BodyElement extends LitElement {
453340
`;
454341
}
455342

456-
private renderValuePreview(
457-
key: string,
458-
value: unknown,
459-
skipHeader = false,
460-
skipCta = false
461-
) {
462-
const ajv = ajvFactory();
463-
const schema = navigateSchema(this.schema!, key) as JSONSchema7;
464-
const compiled = ajv.compile(schema);
465-
const valid = compiled(value);
466-
const description = schema?.description;
467-
const required = this.required.includes(String(key));
468-
469-
return html`
470-
<label
471-
id="#${key}"
472-
class="flex flex-col gap-4 w-full items-start ${when(
473-
!isUndefined(value) && !valid,
474-
() => "error"
475-
)}"
476-
>
477-
${when(!skipHeader && key, () =>
478-
renderLabel(String(key), description, required)
479-
)}
480-
${when(
481-
isUndefined(value) && !skipCta && required,
482-
() => html` <button-element
483-
@click=${() => this.navigate(key)}
484-
emphasis="high"
485-
size="s"
486-
>
487-
Continue</button-element
488-
>`,
489-
() => html`
490-
<div class="flex gap-2">
491-
<button-element
492-
class="w-full min-w-0"
493-
@click=${() => this.navigate(key)}
494-
.state=${valid ? "normal" : "error"}
495-
.iconLeft=${valid ? void 0 : icons.ERROR()}
496-
.icon=${icons.CHEVRON_RIGHT()}
497-
>
498-
${humanizeValue(value).map(
499-
([title]) =>
500-
html`<div class="flex gap-2 min-w-0">
501-
<span
502-
class="truncate text-slate-800 text-left font-medium"
503-
>${title}</span
504-
>
505-
</div>`
506-
)}
507-
</button-element>
508-
509-
${when(
510-
!isUndefined(value),
511-
() => html`<button-element
512-
.icon=${icons.REMOVE()}
513-
@click="${() =>
514-
this.dispatchEvent(
515-
new CustomEvent<ChangeEventDetails>("change", {
516-
detail: {
517-
value: void 0,
518-
path: key,
519-
},
520-
})
521-
)}"
522-
></button-element>`
523-
)}
524-
</div>
525-
`
526-
)}
527-
</label>
528-
`;
529-
}
530-
531343
private renderArray() {
532344
const itemSchema = this.schema?.items as JSONSchema7;
533345
if (!itemSchema) return html`<div>no item schema</div>`;
@@ -584,12 +396,8 @@ export class BodyElement extends LitElement {
584396
<ol class="flex flex-col gap-4 list-decimal">
585397
${((this.value as any[]) ?? []).map(
586398
(value, idx) => html`<li class="ml-6 pl-4">
587-
<div class="flex gap-4 items-baseline">
588-
${when(
589-
PRIMITIVE_TYPES.includes(itemType),
590-
() => this.renderPrimitive(itemType, idx, true),
591-
() => this.renderValuePreview(idx.toString(), value, true, true)
592-
)}
399+
<div class="flex gap-4">
400+
${this.renderProperty(idx, true)}
593401
<button-element
594402
.iconLeft=${icons.REMOVE()}
595403
@click="${() =>

src/constants.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const PATH_UP = Symbol();
1414
// Additional JSON Schema keywords, allowed for strict validation.
1515
export const AJV_ALLOWED_KEYWORDS = ["meta:license"] as const;
1616

17-
export const ALL_TYPES: (JSONSchema7TypeName | "enum" | undefined)[] = [
17+
export const ALL_TYPES: (JSONSchema7TypeName | undefined)[] = [
1818
"string",
1919
"number",
2020
"integer",

0 commit comments

Comments
 (0)