@react-typed-forms/schemas 1.0.0-dev.16 → 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/package-deps_build.json +2 -2
- package/.rush/temp/shrinkwrap-deps.json +5 -3
- 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 +1169 -3044
- 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 +10 -7
- package/src/controlRender.tsx +187 -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,152 +336,92 @@ 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
|
|
|
347
|
+
/** @trackControls */
|
|
340
348
|
function DataRenderer({
|
|
341
349
|
hooks,
|
|
342
350
|
formState,
|
|
343
351
|
controlDef,
|
|
344
|
-
wrapElem,
|
|
345
352
|
fieldData,
|
|
346
353
|
}: {
|
|
347
354
|
hooks: FormEditHooks;
|
|
348
355
|
controlDef: DataControlDefinition;
|
|
349
356
|
formState: FormEditState;
|
|
350
357
|
fieldData: SchemaField;
|
|
351
|
-
wrapElem: (db: ReactElement) => ReactElement;
|
|
352
358
|
}) {
|
|
353
359
|
const renderer = useFormRendererComponents();
|
|
354
|
-
const props = hooks.useDataProperties(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
properties: props,
|
|
360
|
-
};
|
|
361
|
-
return wrapElem(
|
|
362
|
-
(props.customRender ?? renderer.renderData)(
|
|
363
|
-
scalarProps,
|
|
364
|
-
props.control,
|
|
365
|
-
false,
|
|
366
|
-
renderer
|
|
367
|
-
)
|
|
360
|
+
const props = hooks.useDataProperties(
|
|
361
|
+
formState,
|
|
362
|
+
controlDef,
|
|
363
|
+
fieldData,
|
|
364
|
+
renderer,
|
|
368
365
|
);
|
|
366
|
+
return (props.customRender ?? renderer.renderData)(props);
|
|
369
367
|
}
|
|
370
368
|
|
|
369
|
+
/** @trackControls */
|
|
371
370
|
function ActionRenderer({
|
|
372
371
|
hooks,
|
|
373
372
|
formState,
|
|
374
|
-
wrapElem,
|
|
375
373
|
actionDef,
|
|
376
374
|
}: {
|
|
377
375
|
hooks: FormEditHooks;
|
|
378
376
|
actionDef: ActionControlDefinition;
|
|
379
377
|
formState: FormEditState;
|
|
380
|
-
wrapElem: (db: ReactElement) => ReactElement;
|
|
381
378
|
}) {
|
|
382
379
|
const { renderAction } = useFormRendererComponents();
|
|
383
380
|
const actionControlProperties = hooks.useActionProperties(
|
|
384
381
|
formState,
|
|
385
|
-
actionDef
|
|
386
|
-
);
|
|
387
|
-
return wrapElem(
|
|
388
|
-
renderAction({ definition: actionDef, properties: actionControlProperties })
|
|
382
|
+
actionDef,
|
|
389
383
|
);
|
|
384
|
+
return renderAction(actionControlProperties);
|
|
390
385
|
}
|
|
391
386
|
|
|
387
|
+
/** @trackControls */
|
|
392
388
|
function GroupRenderer({
|
|
393
389
|
hooks,
|
|
394
390
|
formState,
|
|
395
391
|
groupDef,
|
|
396
|
-
wrapElem,
|
|
397
392
|
}: {
|
|
398
393
|
hooks: FormEditHooks;
|
|
399
394
|
groupDef: GroupedControlsDefinition;
|
|
400
395
|
formState: FormEditState;
|
|
401
|
-
wrapElem: (db: ReactElement) => ReactElement;
|
|
402
396
|
}) {
|
|
403
397
|
const renderers = useFormRendererComponents();
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
if (compoundField) {
|
|
410
|
-
return wrapElem(
|
|
411
|
-
renderers.renderCompound(
|
|
412
|
-
{
|
|
413
|
-
definition: groupDef,
|
|
414
|
-
field: compoundField,
|
|
415
|
-
properties: groupProps,
|
|
416
|
-
renderChild: (k, c, data, wrapChild) =>
|
|
417
|
-
renderControl(
|
|
418
|
-
c as AnyControlDefinition,
|
|
419
|
-
{
|
|
420
|
-
...formState,
|
|
421
|
-
fields: compoundField!.children,
|
|
422
|
-
data,
|
|
423
|
-
},
|
|
424
|
-
groupProps.hooks,
|
|
425
|
-
k,
|
|
426
|
-
wrapChild
|
|
427
|
-
),
|
|
428
|
-
},
|
|
429
|
-
formState.data.fields[compoundField.field],
|
|
430
|
-
renderers
|
|
431
|
-
)
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
return wrapElem(
|
|
435
|
-
renderers.renderGroup({
|
|
436
|
-
definition: groupDef,
|
|
437
|
-
childCount: groupDef.children.length,
|
|
438
|
-
properties: groupProps,
|
|
439
|
-
renderChild: (c, wrapChild) =>
|
|
440
|
-
renderControl(
|
|
441
|
-
groupDef.children[c],
|
|
442
|
-
formState,
|
|
443
|
-
groupProps.hooks,
|
|
444
|
-
c,
|
|
445
|
-
wrapChild
|
|
446
|
-
),
|
|
447
|
-
})
|
|
398
|
+
const groupProps = hooks.useGroupProperties(
|
|
399
|
+
formState,
|
|
400
|
+
groupDef,
|
|
401
|
+
hooks,
|
|
402
|
+
renderers,
|
|
448
403
|
);
|
|
404
|
+
return renderers.renderGroup(groupProps);
|
|
449
405
|
}
|
|
450
406
|
|
|
407
|
+
/** @trackControls */
|
|
451
408
|
function DisplayRenderer({
|
|
452
409
|
hooks,
|
|
453
|
-
wrapElem,
|
|
454
410
|
formState,
|
|
455
411
|
displayDef,
|
|
456
412
|
}: {
|
|
457
413
|
hooks: FormEditHooks;
|
|
458
414
|
displayDef: DisplayControlDefinition;
|
|
459
415
|
formState: FormEditState;
|
|
460
|
-
wrapElem: (db: ReactElement) => ReactElement;
|
|
461
416
|
}) {
|
|
462
417
|
const { renderDisplay } = useFormRendererComponents();
|
|
463
|
-
|
|
464
418
|
const displayProps = hooks.useDisplayProperties(formState, displayDef);
|
|
465
|
-
return
|
|
466
|
-
renderDisplay({ definition: displayDef, properties: displayProps })
|
|
467
|
-
);
|
|
419
|
+
return renderDisplay(displayProps);
|
|
468
420
|
}
|
|
469
421
|
|
|
470
422
|
export function controlForField(
|
|
471
423
|
field: string,
|
|
472
|
-
formState: FormEditState
|
|
424
|
+
formState: FormEditState,
|
|
473
425
|
): Control<any> {
|
|
474
426
|
const refField = findField(formState.fields, field);
|
|
475
427
|
return (
|
|
@@ -486,13 +438,72 @@ export function fieldForControl(c: ControlDefinition) {
|
|
|
486
438
|
}
|
|
487
439
|
|
|
488
440
|
export function isDataControl(
|
|
489
|
-
c: ControlDefinition
|
|
441
|
+
c: ControlDefinition,
|
|
490
442
|
): c is DataControlDefinition {
|
|
491
443
|
return c.type === ControlDefinitionType.Data;
|
|
492
444
|
}
|
|
493
445
|
|
|
494
446
|
export function isGroupControl(
|
|
495
|
-
c: ControlDefinition
|
|
447
|
+
c: ControlDefinition,
|
|
496
448
|
): c is GroupedControlsDefinition {
|
|
497
449
|
return c.type === ControlDefinitionType.Group;
|
|
498
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
|
+
}
|