@react-typed-forms/schemas 1.0.0-dev.17 → 1.0.0-dev.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rush/temp/operation/build/state.json +1 -1
- package/.rush/temp/shrinkwrap-deps.json +5 -1
- package/lib/controlRender.d.ts +112 -100
- package/lib/hooks.d.ts +11 -9
- package/lib/index.d.ts +7 -5
- package/lib/index.js +1132 -139
- package/lib/index.js.map +1 -1
- package/lib/renderers.d.ts +153 -0
- package/lib/schemaBuilder.d.ts +87 -87
- package/lib/tailwind.d.ts +2 -0
- package/lib/types.d.ts +265 -234
- package/lib/util.d.ts +22 -3
- package/package.json +8 -4
- package/src/controlRender.tsx +172 -275
- package/src/hooks.tsx +441 -0
- package/src/index.ts +2 -0
- package/src/renderers.tsx +855 -0
- package/src/tailwind.tsx +21 -0
- package/src/types.ts +56 -17
- package/src/util.ts +204 -1
- package/src/hooks.ts +0 -173
package/src/controlRender.tsx
CHANGED
|
@@ -1,78 +1,86 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ActionControlDefinition,
|
|
3
|
-
|
|
3
|
+
AdornmentPlacement,
|
|
4
4
|
CompoundField,
|
|
5
|
+
ControlAdornment,
|
|
5
6
|
ControlDefinition,
|
|
6
7
|
ControlDefinitionType,
|
|
7
8
|
DataControlDefinition,
|
|
8
9
|
DisplayControlDefinition,
|
|
9
10
|
EntityExpression,
|
|
10
11
|
FieldOption,
|
|
11
|
-
FieldType,
|
|
12
12
|
GroupedControlsDefinition,
|
|
13
|
+
RenderOptions,
|
|
13
14
|
SchemaField,
|
|
15
|
+
SchemaValidator,
|
|
14
16
|
visitControlDefinition,
|
|
15
17
|
} from "./types";
|
|
16
|
-
import React, {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Key,
|
|
20
|
-
ReactElement,
|
|
21
|
-
ReactNode,
|
|
22
|
-
useContext,
|
|
23
|
-
} from "react";
|
|
24
|
-
import { Control, newControl } from "@react-typed-forms/core";
|
|
25
|
-
import { fieldDisplayName } from "./util";
|
|
18
|
+
import React, {Context, createContext, Key, ReactElement, ReactNode, useContext,} from "react";
|
|
19
|
+
import {Control, newControl} from "@react-typed-forms/core";
|
|
20
|
+
import {fieldDisplayName, findCompoundField, findField, findScalarField, isDataControl, isGroupControl} from "./util";
|
|
26
21
|
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
export interface SchemaHooks {
|
|
23
|
+
useExpression(
|
|
24
|
+
expr: EntityExpression,
|
|
25
|
+
formState: FormEditState,
|
|
26
|
+
): Control<any | undefined>;
|
|
27
|
+
useValidators(
|
|
28
|
+
formState: FormEditState,
|
|
29
|
+
isVisible: boolean,
|
|
30
|
+
control: Control<any>,
|
|
31
|
+
required: boolean,
|
|
32
|
+
validations?: SchemaValidator[] | null,
|
|
33
|
+
): void;
|
|
34
|
+
}
|
|
31
35
|
|
|
32
36
|
export interface FormEditHooks {
|
|
33
37
|
useDataProperties(
|
|
34
38
|
formState: FormEditState,
|
|
35
39
|
definition: DataControlDefinition,
|
|
36
|
-
field: SchemaField
|
|
37
|
-
|
|
40
|
+
field: SchemaField,
|
|
41
|
+
renderers: FormRenderer,
|
|
42
|
+
): DataRendererProps;
|
|
38
43
|
useGroupProperties(
|
|
39
44
|
formState: FormEditState,
|
|
40
45
|
definition: GroupedControlsDefinition,
|
|
41
|
-
currentHooks: FormEditHooks
|
|
42
|
-
|
|
46
|
+
currentHooks: FormEditHooks,
|
|
47
|
+
renderers: FormRenderer,
|
|
48
|
+
): GroupRendererProps;
|
|
43
49
|
useDisplayProperties(
|
|
44
50
|
formState: FormEditState,
|
|
45
|
-
definition: DisplayControlDefinition
|
|
46
|
-
):
|
|
51
|
+
definition: DisplayControlDefinition,
|
|
52
|
+
): DisplayRendererProps;
|
|
47
53
|
useActionProperties(
|
|
48
54
|
formState: FormEditState,
|
|
49
|
-
definition: ActionControlDefinition
|
|
50
|
-
):
|
|
51
|
-
|
|
55
|
+
definition: ActionControlDefinition,
|
|
56
|
+
): ActionRendererProps;
|
|
57
|
+
schemaHooks: SchemaHooks;
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
export interface
|
|
60
|
+
export interface DataRendererProps {
|
|
61
|
+
definition: DataControlDefinition;
|
|
62
|
+
renderOptions: RenderOptions;
|
|
63
|
+
visible: Visibility;
|
|
55
64
|
control: Control<any>;
|
|
56
|
-
|
|
65
|
+
field: SchemaField;
|
|
66
|
+
array?: ArrayRendererProps;
|
|
57
67
|
readonly: boolean;
|
|
58
68
|
defaultValue: any;
|
|
59
69
|
required: boolean;
|
|
60
70
|
options: FieldOption[] | undefined | null;
|
|
61
71
|
customRender?: (props: DataRendererProps) => ReactElement;
|
|
72
|
+
formState: FormEditState;
|
|
62
73
|
}
|
|
63
74
|
|
|
64
|
-
export interface
|
|
65
|
-
|
|
75
|
+
export interface GroupRendererProps {
|
|
76
|
+
definition: Omit<GroupedControlsDefinition, "children">;
|
|
77
|
+
visible: Visibility;
|
|
78
|
+
field?: CompoundField;
|
|
79
|
+
array?: ArrayRendererProps;
|
|
80
|
+
hideTitle: boolean;
|
|
66
81
|
hooks: FormEditHooks;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
export interface DisplayControlProperties {
|
|
70
|
-
visible: boolean;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface ActionControlProperties {
|
|
74
|
-
visible: boolean;
|
|
75
|
-
onClick: () => void;
|
|
82
|
+
childCount: number;
|
|
83
|
+
renderChild: (child: number) => ReactElement;
|
|
76
84
|
}
|
|
77
85
|
|
|
78
86
|
export interface ControlData {
|
|
@@ -83,34 +91,49 @@ export interface FormEditState {
|
|
|
83
91
|
fields: SchemaField[];
|
|
84
92
|
data: Control<ControlData>;
|
|
85
93
|
readonly?: boolean;
|
|
94
|
+
invisible?: boolean;
|
|
86
95
|
}
|
|
87
96
|
|
|
88
|
-
export interface
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
export interface ArrayRendererProps {
|
|
98
|
+
definition: DataControlDefinition | GroupedControlsDefinition;
|
|
99
|
+
control: Control<any[]>;
|
|
100
|
+
field: SchemaField;
|
|
101
|
+
addAction?: ActionRendererProps;
|
|
102
|
+
removeAction?: (childCount: number) => ActionRendererProps;
|
|
103
|
+
childCount: number;
|
|
104
|
+
renderChild: (childCount: number) => ReactElement;
|
|
105
|
+
childKey: (childCount: number) => Key;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface AdornmentProps {
|
|
109
|
+
key: Key;
|
|
110
|
+
definition: ControlAdornment;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface AdornmentRenderer {
|
|
114
|
+
wrap?: (children: ReactElement) => ReactElement;
|
|
115
|
+
child?: [AdornmentPlacement, ReactNode];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface FormRenderer {
|
|
119
|
+
renderData: (props: DataRendererProps) => ReactElement;
|
|
100
120
|
renderGroup: (props: GroupRendererProps) => ReactElement;
|
|
101
121
|
renderDisplay: (props: DisplayRendererProps) => ReactElement;
|
|
102
122
|
renderAction: (props: ActionRendererProps) => ReactElement;
|
|
123
|
+
renderArray: (props: ArrayRendererProps) => ReactElement;
|
|
124
|
+
renderLabel: (props: LabelRendererProps, elem: ReactElement) => ReactElement;
|
|
125
|
+
renderVisibility: (visible: Visibility, elem: ReactElement) => ReactElement;
|
|
126
|
+
renderAdornment: (props: AdornmentProps) => AdornmentRenderer;
|
|
103
127
|
}
|
|
104
128
|
|
|
105
|
-
let _FormRendererComponentsContext: Context<
|
|
106
|
-
|
|
107
|
-
> | null = null;
|
|
129
|
+
let _FormRendererComponentsContext: Context<FormRenderer | undefined> | null =
|
|
130
|
+
null;
|
|
108
131
|
|
|
109
132
|
function FormRendererComponentsContext() {
|
|
110
133
|
if (!_FormRendererComponentsContext) {
|
|
111
|
-
_FormRendererComponentsContext = createContext<
|
|
112
|
-
|
|
113
|
-
|
|
134
|
+
_FormRendererComponentsContext = createContext<FormRenderer | undefined>(
|
|
135
|
+
undefined,
|
|
136
|
+
);
|
|
114
137
|
}
|
|
115
138
|
return _FormRendererComponentsContext;
|
|
116
139
|
}
|
|
@@ -119,7 +142,7 @@ export function FormRendererProvider({
|
|
|
119
142
|
value,
|
|
120
143
|
children,
|
|
121
144
|
}: {
|
|
122
|
-
value:
|
|
145
|
+
value: FormRenderer;
|
|
123
146
|
children: ReactNode;
|
|
124
147
|
}) {
|
|
125
148
|
const { Provider } = FormRendererComponentsContext();
|
|
@@ -134,144 +157,38 @@ export function useFormRendererComponents() {
|
|
|
134
157
|
return c;
|
|
135
158
|
}
|
|
136
159
|
|
|
160
|
+
export interface Visibility {
|
|
161
|
+
value: boolean;
|
|
162
|
+
canChange: boolean;
|
|
163
|
+
}
|
|
164
|
+
export interface LabelRendererProps {
|
|
165
|
+
visible: Visibility;
|
|
166
|
+
title?: ReactNode;
|
|
167
|
+
forId?: string;
|
|
168
|
+
required: boolean;
|
|
169
|
+
control?: Control<any>;
|
|
170
|
+
group?: boolean;
|
|
171
|
+
renderAdornment: (placement: AdornmentPlacement) => ReactElement;
|
|
172
|
+
}
|
|
173
|
+
|
|
137
174
|
export interface DisplayRendererProps {
|
|
138
175
|
definition: DisplayControlDefinition;
|
|
139
|
-
|
|
176
|
+
visible: Visibility;
|
|
140
177
|
}
|
|
141
178
|
|
|
142
179
|
export interface ActionRendererProps {
|
|
143
180
|
definition: ActionControlDefinition;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
export interface DataRendererProps {
|
|
148
|
-
definition: DataControlDefinition;
|
|
149
|
-
properties: DataControlProperties;
|
|
150
|
-
field: SchemaField;
|
|
151
|
-
formEditState?: FormEditState;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export interface GroupRendererProps {
|
|
155
|
-
definition: Omit<GroupedControlsDefinition, "children">;
|
|
156
|
-
properties: GroupControlProperties;
|
|
157
|
-
childCount: number;
|
|
158
|
-
renderChild: (
|
|
159
|
-
child: number,
|
|
160
|
-
wrapChild: (key: Key, childElem: ReactElement) => ReactElement
|
|
161
|
-
) => ReactElement;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export interface CompoundGroupRendererProps {
|
|
165
|
-
definition: GroupedControlsDefinition;
|
|
166
|
-
field: CompoundField;
|
|
167
|
-
properties: GroupControlProperties;
|
|
168
|
-
renderChild: (
|
|
169
|
-
key: Key,
|
|
170
|
-
control: ControlDefinition,
|
|
171
|
-
data: Control<{
|
|
172
|
-
[field: string]: any;
|
|
173
|
-
}>,
|
|
174
|
-
wrapChild: (key: Key, childElem: ReactElement) => ReactElement
|
|
175
|
-
) => ReactElement;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export function isScalarField(sf: SchemaField): sf is SchemaField {
|
|
179
|
-
return !isCompoundField(sf);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export function isCompoundField(sf: SchemaField): sf is CompoundField {
|
|
183
|
-
return sf.type === FieldType.Compound;
|
|
181
|
+
visible: Visibility;
|
|
182
|
+
onClick: () => void;
|
|
184
183
|
}
|
|
185
184
|
|
|
186
185
|
export type AnySchemaFields =
|
|
187
186
|
| SchemaField
|
|
188
187
|
| (Omit<CompoundField, "children"> & { children: AnySchemaFields[] });
|
|
189
188
|
|
|
190
|
-
export function applyDefaultValues(
|
|
191
|
-
v: { [k: string]: any } | undefined,
|
|
192
|
-
fields: SchemaField[]
|
|
193
|
-
): any {
|
|
194
|
-
if (!v) return defaultValueForFields(fields);
|
|
195
|
-
const applyValue = fields.filter(
|
|
196
|
-
(x) => isCompoundField(x) || !(x.field in v)
|
|
197
|
-
);
|
|
198
|
-
if (!applyValue.length) return v;
|
|
199
|
-
const out = { ...v };
|
|
200
|
-
applyValue.forEach((x) => {
|
|
201
|
-
out[x.field] =
|
|
202
|
-
x.field in v
|
|
203
|
-
? applyDefaultForField(v[x.field], x, fields)
|
|
204
|
-
: defaultValueForField(x);
|
|
205
|
-
});
|
|
206
|
-
return out;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export function applyDefaultForField(
|
|
210
|
-
v: any,
|
|
211
|
-
field: SchemaField,
|
|
212
|
-
parent: SchemaField[],
|
|
213
|
-
notElement?: boolean
|
|
214
|
-
): any {
|
|
215
|
-
if (field.collection && !notElement) {
|
|
216
|
-
return ((v as any[]) ?? []).map((x) =>
|
|
217
|
-
applyDefaultForField(x, field, parent, true)
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
if (isCompoundField(field)) {
|
|
221
|
-
if (!v && !field.required) return v;
|
|
222
|
-
return applyDefaultValues(v, field.treeChildren ? parent : field.children);
|
|
223
|
-
}
|
|
224
|
-
return defaultValueForField(field);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export function defaultValueForFields(fields: SchemaField[]): any {
|
|
228
|
-
return Object.fromEntries(
|
|
229
|
-
fields.map((x) => [x.field, defaultValueForField(x)])
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export function defaultValueForField(sf: SchemaField): any {
|
|
234
|
-
if (isCompoundField(sf)) {
|
|
235
|
-
return sf.required
|
|
236
|
-
? sf.collection
|
|
237
|
-
? []
|
|
238
|
-
: defaultValueForFields(sf.children)
|
|
239
|
-
: undefined;
|
|
240
|
-
}
|
|
241
|
-
if (sf.collection) return [];
|
|
242
|
-
return sf.defaultValue;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
export function elementValueForField(sf: SchemaField): any {
|
|
246
|
-
if (isCompoundField(sf)) {
|
|
247
|
-
return defaultValueForFields(sf.children);
|
|
248
|
-
}
|
|
249
|
-
return sf.defaultValue;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
export function findScalarField(
|
|
253
|
-
fields: SchemaField[],
|
|
254
|
-
field: string
|
|
255
|
-
): SchemaField | undefined {
|
|
256
|
-
return findField(fields, field);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
export function findCompoundField(
|
|
260
|
-
fields: SchemaField[],
|
|
261
|
-
field: string
|
|
262
|
-
): CompoundField | undefined {
|
|
263
|
-
return findField(fields, field) as CompoundField | undefined;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
export function findField(
|
|
267
|
-
fields: SchemaField[],
|
|
268
|
-
field: string
|
|
269
|
-
): SchemaField | undefined {
|
|
270
|
-
return fields.find((x) => x.field === field);
|
|
271
|
-
}
|
|
272
189
|
export function controlTitle(
|
|
273
190
|
title: string | undefined | null,
|
|
274
|
-
field: SchemaField
|
|
191
|
+
field: SchemaField,
|
|
275
192
|
) {
|
|
276
193
|
return title ? title : fieldDisplayName(field);
|
|
277
194
|
}
|
|
@@ -281,7 +198,6 @@ export function renderControl<S extends ControlDefinition>(
|
|
|
281
198
|
formState: FormEditState,
|
|
282
199
|
hooks: FormEditHooks,
|
|
283
200
|
key: Key,
|
|
284
|
-
wrapChild?: (key: Key, db: ReactElement) => ReactElement
|
|
285
201
|
): ReactElement {
|
|
286
202
|
const { fields } = formState;
|
|
287
203
|
return visitControlDefinition(
|
|
@@ -289,11 +205,11 @@ export function renderControl<S extends ControlDefinition>(
|
|
|
289
205
|
{
|
|
290
206
|
data: (def) => {
|
|
291
207
|
const fieldData = findScalarField(fields, def.field);
|
|
292
|
-
if (!fieldData)
|
|
208
|
+
if (!fieldData)
|
|
209
|
+
return <h1 key={key}>No schema field for: {def.field}</h1>;
|
|
293
210
|
return (
|
|
294
211
|
<DataRenderer
|
|
295
212
|
key={key}
|
|
296
|
-
wrapElem={wrapElem}
|
|
297
213
|
formState={formState}
|
|
298
214
|
hooks={hooks}
|
|
299
215
|
controlDef={def}
|
|
@@ -307,7 +223,6 @@ export function renderControl<S extends ControlDefinition>(
|
|
|
307
223
|
hooks={hooks}
|
|
308
224
|
groupDef={d}
|
|
309
225
|
formState={formState}
|
|
310
|
-
wrapElem={wrapElem}
|
|
311
226
|
/>
|
|
312
227
|
),
|
|
313
228
|
action: (d: ActionControlDefinition) => (
|
|
@@ -315,7 +230,6 @@ export function renderControl<S extends ControlDefinition>(
|
|
|
315
230
|
key={key}
|
|
316
231
|
hooks={hooks}
|
|
317
232
|
formState={formState}
|
|
318
|
-
wrapElem={wrapElem}
|
|
319
233
|
actionDef={d}
|
|
320
234
|
/>
|
|
321
235
|
),
|
|
@@ -324,17 +238,12 @@ export function renderControl<S extends ControlDefinition>(
|
|
|
324
238
|
key={key}
|
|
325
239
|
hooks={hooks}
|
|
326
240
|
formState={formState}
|
|
327
|
-
wrapElem={wrapElem}
|
|
328
241
|
displayDef={d}
|
|
329
242
|
/>
|
|
330
243
|
),
|
|
331
244
|
},
|
|
332
|
-
() => <h1>Unknown control: {(definition as any).type}</h1
|
|
245
|
+
() => <h1>Unknown control: {(definition as any).type}</h1>,
|
|
333
246
|
);
|
|
334
|
-
|
|
335
|
-
function wrapElem(e: ReactElement): ReactElement {
|
|
336
|
-
return wrapChild?.(key, e) ?? e;
|
|
337
|
-
}
|
|
338
247
|
}
|
|
339
248
|
|
|
340
249
|
/** @trackControls */
|
|
@@ -342,53 +251,39 @@ function DataRenderer({
|
|
|
342
251
|
hooks,
|
|
343
252
|
formState,
|
|
344
253
|
controlDef,
|
|
345
|
-
wrapElem,
|
|
346
254
|
fieldData,
|
|
347
255
|
}: {
|
|
348
256
|
hooks: FormEditHooks;
|
|
349
257
|
controlDef: DataControlDefinition;
|
|
350
258
|
formState: FormEditState;
|
|
351
259
|
fieldData: SchemaField;
|
|
352
|
-
wrapElem: (db: ReactElement) => ReactElement;
|
|
353
260
|
}) {
|
|
354
261
|
const renderer = useFormRendererComponents();
|
|
355
|
-
const props = hooks.useDataProperties(
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
properties: props,
|
|
361
|
-
};
|
|
362
|
-
return wrapElem(
|
|
363
|
-
(props.customRender ?? renderer.renderData)(
|
|
364
|
-
scalarProps,
|
|
365
|
-
props.control,
|
|
366
|
-
false,
|
|
367
|
-
renderer
|
|
368
|
-
)
|
|
262
|
+
const props = hooks.useDataProperties(
|
|
263
|
+
formState,
|
|
264
|
+
controlDef,
|
|
265
|
+
fieldData,
|
|
266
|
+
renderer,
|
|
369
267
|
);
|
|
268
|
+
return (props.customRender ?? renderer.renderData)(props);
|
|
370
269
|
}
|
|
371
270
|
|
|
372
271
|
/** @trackControls */
|
|
373
272
|
function ActionRenderer({
|
|
374
273
|
hooks,
|
|
375
274
|
formState,
|
|
376
|
-
wrapElem,
|
|
377
275
|
actionDef,
|
|
378
276
|
}: {
|
|
379
277
|
hooks: FormEditHooks;
|
|
380
278
|
actionDef: ActionControlDefinition;
|
|
381
279
|
formState: FormEditState;
|
|
382
|
-
wrapElem: (db: ReactElement) => ReactElement;
|
|
383
280
|
}) {
|
|
384
281
|
const { renderAction } = useFormRendererComponents();
|
|
385
282
|
const actionControlProperties = hooks.useActionProperties(
|
|
386
283
|
formState,
|
|
387
|
-
actionDef
|
|
388
|
-
);
|
|
389
|
-
return wrapElem(
|
|
390
|
-
renderAction({ definition: actionDef, properties: actionControlProperties })
|
|
284
|
+
actionDef,
|
|
391
285
|
);
|
|
286
|
+
return renderAction(actionControlProperties);
|
|
392
287
|
}
|
|
393
288
|
|
|
394
289
|
/** @trackControls */
|
|
@@ -396,84 +291,39 @@ function GroupRenderer({
|
|
|
396
291
|
hooks,
|
|
397
292
|
formState,
|
|
398
293
|
groupDef,
|
|
399
|
-
wrapElem,
|
|
400
294
|
}: {
|
|
401
295
|
hooks: FormEditHooks;
|
|
402
296
|
groupDef: GroupedControlsDefinition;
|
|
403
297
|
formState: FormEditState;
|
|
404
|
-
wrapElem: (db: ReactElement) => ReactElement;
|
|
405
298
|
}) {
|
|
406
299
|
const renderers = useFormRendererComponents();
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
if (compoundField) {
|
|
413
|
-
return wrapElem(
|
|
414
|
-
renderers.renderCompound(
|
|
415
|
-
{
|
|
416
|
-
definition: groupDef,
|
|
417
|
-
field: compoundField,
|
|
418
|
-
properties: groupProps,
|
|
419
|
-
renderChild: (k, c, data, wrapChild) =>
|
|
420
|
-
renderControl(
|
|
421
|
-
c as AnyControlDefinition,
|
|
422
|
-
{
|
|
423
|
-
...formState,
|
|
424
|
-
fields: compoundField!.children,
|
|
425
|
-
data,
|
|
426
|
-
},
|
|
427
|
-
groupProps.hooks,
|
|
428
|
-
k,
|
|
429
|
-
wrapChild
|
|
430
|
-
),
|
|
431
|
-
},
|
|
432
|
-
formState.data.fields[compoundField.field],
|
|
433
|
-
renderers
|
|
434
|
-
)
|
|
435
|
-
);
|
|
436
|
-
}
|
|
437
|
-
return wrapElem(
|
|
438
|
-
renderers.renderGroup({
|
|
439
|
-
definition: groupDef,
|
|
440
|
-
childCount: groupDef.children.length,
|
|
441
|
-
properties: groupProps,
|
|
442
|
-
renderChild: (c, wrapChild) =>
|
|
443
|
-
renderControl(
|
|
444
|
-
groupDef.children[c],
|
|
445
|
-
formState,
|
|
446
|
-
groupProps.hooks,
|
|
447
|
-
c,
|
|
448
|
-
wrapChild
|
|
449
|
-
),
|
|
450
|
-
})
|
|
300
|
+
const groupProps = hooks.useGroupProperties(
|
|
301
|
+
formState,
|
|
302
|
+
groupDef,
|
|
303
|
+
hooks,
|
|
304
|
+
renderers,
|
|
451
305
|
);
|
|
306
|
+
return renderers.renderGroup(groupProps);
|
|
452
307
|
}
|
|
453
308
|
|
|
454
309
|
/** @trackControls */
|
|
455
310
|
function DisplayRenderer({
|
|
456
311
|
hooks,
|
|
457
|
-
wrapElem,
|
|
458
312
|
formState,
|
|
459
313
|
displayDef,
|
|
460
314
|
}: {
|
|
461
315
|
hooks: FormEditHooks;
|
|
462
316
|
displayDef: DisplayControlDefinition;
|
|
463
317
|
formState: FormEditState;
|
|
464
|
-
wrapElem: (db: ReactElement) => ReactElement;
|
|
465
318
|
}) {
|
|
466
319
|
const { renderDisplay } = useFormRendererComponents();
|
|
467
|
-
|
|
468
320
|
const displayProps = hooks.useDisplayProperties(formState, displayDef);
|
|
469
|
-
return
|
|
470
|
-
renderDisplay({ definition: displayDef, properties: displayProps })
|
|
471
|
-
);
|
|
321
|
+
return renderDisplay(displayProps);
|
|
472
322
|
}
|
|
473
323
|
|
|
474
324
|
export function controlForField(
|
|
475
325
|
field: string,
|
|
476
|
-
formState: FormEditState
|
|
326
|
+
formState: FormEditState,
|
|
477
327
|
): Control<any> {
|
|
478
328
|
const refField = findField(formState.fields, field);
|
|
479
329
|
return (
|
|
@@ -489,14 +339,61 @@ export function fieldForControl(c: ControlDefinition) {
|
|
|
489
339
|
: undefined;
|
|
490
340
|
}
|
|
491
341
|
|
|
492
|
-
export
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
342
|
+
export const AlwaysVisible: Visibility = { value: true, canChange: false };
|
|
343
|
+
|
|
344
|
+
export function createAction(
|
|
345
|
+
label: string,
|
|
346
|
+
onClick: () => void,
|
|
347
|
+
actionId?: string,
|
|
348
|
+
): ActionRendererProps {
|
|
349
|
+
return {
|
|
350
|
+
definition: {
|
|
351
|
+
type: ControlDefinitionType.Action,
|
|
352
|
+
actionId: actionId ?? label,
|
|
353
|
+
title: label,
|
|
354
|
+
},
|
|
355
|
+
visible: AlwaysVisible,
|
|
356
|
+
onClick,
|
|
357
|
+
};
|
|
496
358
|
}
|
|
497
359
|
|
|
498
|
-
export function
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
360
|
+
export function visitControlData<S extends ControlDefinition, A>(
|
|
361
|
+
definition: S,
|
|
362
|
+
{ fields, data }: FormEditState,
|
|
363
|
+
cb: (
|
|
364
|
+
definition: DataControlDefinition,
|
|
365
|
+
control: Control<any>,
|
|
366
|
+
) => A | undefined,
|
|
367
|
+
): A | undefined {
|
|
368
|
+
return visitControlDefinition<A | undefined>(
|
|
369
|
+
definition,
|
|
370
|
+
{
|
|
371
|
+
data(def: DataControlDefinition) {
|
|
372
|
+
const fieldData = findScalarField(fields, def.field);
|
|
373
|
+
if (!fieldData) return undefined;
|
|
374
|
+
return cb(def, data.fields[fieldData.field]);
|
|
375
|
+
},
|
|
376
|
+
group(d: GroupedControlsDefinition) {
|
|
377
|
+
if (d.compoundField) {
|
|
378
|
+
const compound = findCompoundField(fields, d.compoundField);
|
|
379
|
+
if (!compound) return;
|
|
380
|
+
fields = compound.children;
|
|
381
|
+
data = data.fields[compound.field];
|
|
382
|
+
}
|
|
383
|
+
const childState = { fields, data };
|
|
384
|
+
for (let c of d.children) {
|
|
385
|
+
const res = visitControlData(c, childState, cb);
|
|
386
|
+
if (res !== undefined) return res;
|
|
387
|
+
}
|
|
388
|
+
return undefined;
|
|
389
|
+
},
|
|
390
|
+
action(d: ActionControlDefinition) {
|
|
391
|
+
return undefined;
|
|
392
|
+
},
|
|
393
|
+
display(d: DisplayControlDefinition) {
|
|
394
|
+
return undefined;
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
() => undefined,
|
|
398
|
+
);
|
|
502
399
|
}
|