Skip to content

Commit 208e596

Browse files
committed
feat: ui schema title + desc., better date formats
1 parent de1f6a8 commit 208e596

File tree

7 files changed

+67
-26
lines changed

7 files changed

+67
-26
lines changed

packages/form/src/json-schema-form.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { fieldArrayPrimitive } from './triage/array-primitive';
21
/* eslint-disable max-lines */
32
/* eslint-disable class-methods-use-this */
43
/* eslint-disable no-underscore-dangle */
@@ -9,6 +8,7 @@ import {
98
unsafeCSS,
109
type TemplateResult,
1110
type CSSResult,
11+
nothing,
1212
} from 'lit';
1313

1414
import { property, state } from 'lit/decorators.js';
@@ -17,12 +17,11 @@ import { createRef, ref } from 'lit/directives/ref.js';
1717
// import deepmerge from 'deepmerge';
1818
import set from 'lodash-es/set';
1919

20-
import type { JSONSchema7 } from '@jsfe/types';
21-
2220
// import { alternateField } from './triage/alternate.js';
2321
import { fieldArray } from './triage/array.js';
2422
import { fieldObject } from './triage/object.js';
2523
import { fieldPrimitive } from './triage/primitive.js';
24+
import { fieldArrayPrimitive } from './triage/array-primitive.js';
2625

2726
import type {
2827
DataChangeCallback,
@@ -31,6 +30,7 @@ import type {
3130
Path,
3231
UiSchema,
3332
Widgets,
33+
JSONSchema7,
3434
} from '@jsfe/types';
3535

3636
export class Jsf extends LitElement {
@@ -50,9 +50,11 @@ export class Jsf extends LitElement {
5050

5151
@property({ type: Object }) public experimental?: FeatureFlags = {};
5252

53+
@property({ type: Boolean }) public submitButton = true;
54+
5355
@state() private _uiState: unknown = {};
5456

55-
protected _dig = (
57+
protected _dig(
5658
node: JSONSchema7,
5759
dataLevel: unknown,
5860
path: Path,
@@ -61,7 +63,7 @@ export class Jsf extends LitElement {
6163
schemaPath: Path,
6264
required = false,
6365
level = 0,
64-
): TemplateResult<1> => {
66+
): TemplateResult<1> {
6567
let result: TemplateResult<1> | undefined;
6668
const currentNode: JSONSchema7 = node;
6769

@@ -291,13 +293,14 @@ export class Jsf extends LitElement {
291293
// )}`;
292294
// }
293295

294-
if (Object.entries(node).length === 0) {
295-
const error = `Empty schema`;
296-
return (
297-
this.widgets?.callout?.({ id: '', message: error }) ??
298-
html`<p>${error}</p>`
299-
);
300-
}
296+
// TODO: check for blank schema
297+
// if (Object.entries({ ...node, title: undefined }).length === 0) {
298+
// const error = `Empty schema`;
299+
// return (
300+
// this.widgets?.callout?.({ id: '', message: error }) ??
301+
// html`<p>${error}</p>`
302+
// );
303+
// }
301304

302305
if (result) return result;
303306

@@ -308,7 +311,7 @@ export class Jsf extends LitElement {
308311
this.widgets?.callout?.({ id: '', message: error }) ??
309312
html`<p>${error}</p>`
310313
);
311-
};
314+
}
312315

313316
protected _setToValue(object: unknown, value: unknown, path: Path) {
314317
// NOTE: Dirty method:
@@ -436,10 +439,9 @@ export class Jsf extends LitElement {
436439
[],
437440
false,
438441
)}
439-
<!-- -->
440442
441-
<!-- $ {JSON.stringify(this.widgets)} -->
442-
${this.#submit()}
443+
<!-- -->
444+
${this.submitButton ? this.#submit() : nothing}
443445
</form>
444446
`;
445447
}

packages/form/src/triage/array.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export const fieldArray = (
6060
dataLevel[index],
6161
[...path, index],
6262
uiState,
63-
uiSchema,
63+
uiSchema?.[index],
6464
schemaPathAugmented,
6565
required,
6666
level + 1,
@@ -162,8 +162,9 @@ export const fieldArray = (
162162
) {
163163
itemLabel = schema.items.title;
164164
}
165+
const arrayLabel = schema.title ?? uiSchema?.['ui:title'];
165166
const options = {
166-
label: schema.title,
167+
label: arrayLabel,
167168

168169
items,
169170

packages/form/src/triage/object.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export const fieldObject = (
5656
} else if (typeof key !== 'number') {
5757
label = key;
5858
}
59+
if (typeof uiSchema?.['ui:title'] === 'string') label = uiSchema['ui:title'];
5960

6061
const options = {
6162
id: path.join('.'),

packages/form/src/triage/primitive.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,16 @@ export const fieldPrimitive = (
3535
else if (Number.isNaN(Number(path.at(-1)))) {
3636
label = String(path.at(-1));
3737
}
38+
if (uiOptions?.['ui:title']) {
39+
label = uiOptions?.['ui:title'];
40+
}
3841

3942
const helpText =
40-
schema.description ?? (uiOptions?.['ui:help'] as string) ?? '';
41-
const placeholder = (uiOptions?.['ui:placeholder'] as string) ?? '';
43+
uiOptions?.['ui:help'] ??
44+
uiOptions?.['ui:description'] ??
45+
schema.description ??
46+
'';
47+
const placeholder = uiOptions?.['ui:placeholder'] ?? '';
4248

4349
let baseValue: unknown;
4450

@@ -120,13 +126,30 @@ export const fieldPrimitive = (
120126
schema.format === 'time'
121127
) {
122128
let type = schema.format;
129+
let date = baseValue;
130+
131+
if (date) {
132+
if (schema.format === 'date') {
133+
// date = new Date(date).toISOString().split('T')[0];
134+
}
135+
if (schema.format === 'time') {
136+
// // date = date.toISOString().split('T')[1].split('.')[0];
137+
// // console.log({ date });
138+
}
139+
if (schema.format === 'date-time') {
140+
if (date instanceof Date === false) {
141+
date = new Date(date);
142+
}
143+
if (date instanceof Date) date = date.toISOString().split('.')[0];
144+
}
145+
}
123146

124147
if (schema.format === 'date-time') {
125148
type = 'datetime-local';
126149
}
127150
const options = {
128151
...baseOptions,
129-
value: baseValue ? new Date(String(baseValue)) : undefined,
152+
value: date,
130153
type,
131154
};
132155

@@ -139,6 +162,10 @@ export const fieldPrimitive = (
139162
inputType = schema.format;
140163
}
141164

165+
if (uiOptions?.['ui:widget'] === 'password') {
166+
inputType = 'password';
167+
}
168+
142169
if (uiOptions?.['ui:options']?.inputType === 'tel') {
143170
inputType = 'tel';
144171
}
@@ -158,7 +185,9 @@ export const fieldPrimitive = (
158185
}
159186
if (typeof uiOptions?.['ui:widget'] === 'string') {
160187
const customWidgetName = uiOptions?.['ui:widget'];
161-
return widgets?.[customWidgetName]?.(options) || missing('custom');
188+
if (customWidgetName !== 'password') {
189+
return widgets?.[customWidgetName]?.(options) || missing('custom');
190+
}
162191
}
163192

164193
return widgets?.text?.(options) || missing('text');

packages/shoelace/src/widgets/date.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,21 @@ export const date: Widgets['date'] = (options) => html`
1111
type=${options.type}
1212
.label=${options.label ?? ''}
1313
.helpText=${options.helpText ?? ''}
14-
value=${options.value ? String(options.value) : ''}
14+
value=${options.value ? options.value : ''}
1515
.name=${options.id}
1616
.id=${options.id}
1717
.required=${options.required ?? false}
1818
@sl-input=${(event: CustomEvent) => {
19-
const { valueAsDate: newValue, value } = event.target as SlInput;
19+
let { value } = event.target as SlInput;
20+
21+
if (options.type === 'datetime-local') {
22+
value = new Date(value);
23+
}
2024
2125
options.valueChangedCallback?.(
2226
// NOTE: Date time does not return `valueAsDate`
23-
newValue ?? value ? new Date(value) : undefined,
27+
// TODO: valueChangedCallback should coerce to Date later (when possible)
28+
value,
2429
);
2530
}}
2631
>

packages/types/src/ui-schema.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ export type UiOptions = {
22
'ui:help'?: string;
33
'ui:placeholder'?: string;
44

5+
'ui:title'?: string;
6+
'ui:description'?: string;
7+
58
'ui:widget'?:
69
| 'radio'
710
| 'button'

packages/types/src/widgets.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export interface Widgets {
5757
{
5858
type: 'date' | 'datetime-local' | 'time';
5959
},
60-
Date | undefined
60+
Date | string | undefined
6161
>;
6262

6363
rating?: Widget<

0 commit comments

Comments
 (0)