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