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