@react-typed-forms/schemas 5.0.2 → 6.0.0
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/lib/controlBuilder.d.ts +2 -2
- package/lib/controlRender.d.ts +63 -16
- package/lib/hooks.d.ts +10 -5
- package/lib/index.d.ts +1 -0
- package/lib/index.js +434 -162
- package/lib/index.js.map +1 -1
- package/lib/internal.d.ts +1 -0
- package/lib/renderers.d.ts +20 -10
- package/lib/schemaInterface.d.ts +4 -0
- package/lib/types.d.ts +47 -8
- package/lib/util.d.ts +7 -5
- package/lib/validators.d.ts +2 -2
- package/package.json +2 -2
- package/src/controlBuilder.ts +3 -3
- package/src/controlRender.tsx +198 -82
- package/src/hooks.tsx +102 -17
- package/src/index.ts +1 -0
- package/src/internal.ts +4 -0
- package/src/renderers.tsx +196 -65
- package/src/schemaInterface.ts +31 -0
- package/src/tailwind.tsx +5 -1
- package/src/types.ts +61 -5
- package/src/util.ts +24 -8
- package/src/validators.ts +3 -3
package/src/hooks.tsx
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ControlDefinition,
|
|
3
|
+
DataExpression,
|
|
4
|
+
DataMatchExpression,
|
|
3
5
|
DynamicPropertyType,
|
|
4
6
|
EntityExpression,
|
|
5
7
|
ExpressionType,
|
|
6
|
-
FieldValueExpression,
|
|
7
8
|
isDataControlDefinition,
|
|
8
9
|
JsonataExpression,
|
|
9
10
|
SchemaField,
|
|
11
|
+
SchemaInterface,
|
|
10
12
|
} from "./types";
|
|
11
13
|
import { useCallback, useMemo } from "react";
|
|
12
14
|
import {
|
|
@@ -17,9 +19,10 @@ import {
|
|
|
17
19
|
} from "@react-typed-forms/core";
|
|
18
20
|
|
|
19
21
|
import {
|
|
20
|
-
|
|
22
|
+
ControlDataContext,
|
|
21
23
|
defaultValueForField,
|
|
22
24
|
findField,
|
|
25
|
+
getDisplayOnlyOptions,
|
|
23
26
|
getTypeField,
|
|
24
27
|
isControlReadonly,
|
|
25
28
|
useUpdatedRef,
|
|
@@ -41,13 +44,23 @@ export function useEvalVisibilityHook(
|
|
|
41
44
|
DynamicPropertyType.Visible,
|
|
42
45
|
useEvalExpressionHook,
|
|
43
46
|
);
|
|
44
|
-
const r = useUpdatedRef(schemaField);
|
|
47
|
+
const r = useUpdatedRef({ schemaField, definition });
|
|
45
48
|
return useCallback(
|
|
46
49
|
(ctx) => {
|
|
47
|
-
const schemaField = r.current;
|
|
50
|
+
const { schemaField, definition } = r.current;
|
|
48
51
|
return (
|
|
49
52
|
dynamicVisibility?.(ctx) ??
|
|
50
|
-
useComputed(
|
|
53
|
+
useComputed(
|
|
54
|
+
() =>
|
|
55
|
+
matchesType(ctx, schemaField?.onlyForTypes) &&
|
|
56
|
+
(!schemaField ||
|
|
57
|
+
!hideDisplayOnly(
|
|
58
|
+
ctx,
|
|
59
|
+
schemaField,
|
|
60
|
+
definition,
|
|
61
|
+
ctx.schemaInterface,
|
|
62
|
+
)),
|
|
63
|
+
)
|
|
51
64
|
);
|
|
52
65
|
},
|
|
53
66
|
[dynamicVisibility, r],
|
|
@@ -73,6 +86,25 @@ export function useEvalReadonlyHook(
|
|
|
73
86
|
);
|
|
74
87
|
}
|
|
75
88
|
|
|
89
|
+
export function useEvalStyleHook(
|
|
90
|
+
useEvalExpressionHook: UseEvalExpressionHook,
|
|
91
|
+
property: DynamicPropertyType,
|
|
92
|
+
definition: ControlDefinition,
|
|
93
|
+
): EvalExpressionHook<React.CSSProperties> {
|
|
94
|
+
const dynamicStyle = useEvalDynamicHook(
|
|
95
|
+
definition,
|
|
96
|
+
property,
|
|
97
|
+
useEvalExpressionHook,
|
|
98
|
+
);
|
|
99
|
+
return useCallback(
|
|
100
|
+
(ctx) => {
|
|
101
|
+
if (dynamicStyle) return dynamicStyle(ctx);
|
|
102
|
+
return useControl(undefined);
|
|
103
|
+
},
|
|
104
|
+
[dynamicStyle],
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
76
108
|
export function useEvalDisabledHook(
|
|
77
109
|
useEvalExpressionHook: UseEvalExpressionHook,
|
|
78
110
|
definition: ControlDefinition,
|
|
@@ -91,6 +123,19 @@ export function useEvalDisabledHook(
|
|
|
91
123
|
);
|
|
92
124
|
}
|
|
93
125
|
|
|
126
|
+
export function useEvalDisplayHook(
|
|
127
|
+
useEvalExpressionHook: UseEvalExpressionHook,
|
|
128
|
+
definition: ControlDefinition,
|
|
129
|
+
): (
|
|
130
|
+
groupContext: ControlDataContext,
|
|
131
|
+
) => Control<string | undefined> | undefined {
|
|
132
|
+
const dynamicDisplay = useEvalDynamicHook(
|
|
133
|
+
definition,
|
|
134
|
+
DynamicPropertyType.Display,
|
|
135
|
+
useEvalExpressionHook,
|
|
136
|
+
);
|
|
137
|
+
return useCallback((ctx) => dynamicDisplay?.(ctx), [dynamicDisplay]);
|
|
138
|
+
}
|
|
94
139
|
export function useEvalDefaultValueHook(
|
|
95
140
|
useEvalExpressionHook: UseEvalExpressionHook,
|
|
96
141
|
definition: ControlDefinition,
|
|
@@ -123,11 +168,21 @@ export function useEvalDefaultValueHook(
|
|
|
123
168
|
}
|
|
124
169
|
|
|
125
170
|
export type EvalExpressionHook<A = any> = (
|
|
126
|
-
groupContext:
|
|
171
|
+
groupContext: ControlDataContext,
|
|
127
172
|
) => Control<A | undefined>;
|
|
128
173
|
|
|
129
|
-
function
|
|
130
|
-
fvExpr:
|
|
174
|
+
function useDataExpression(
|
|
175
|
+
fvExpr: DataExpression,
|
|
176
|
+
fields: SchemaField[],
|
|
177
|
+
data: Control<any>,
|
|
178
|
+
) {
|
|
179
|
+
const refField = findField(fields, fvExpr.field);
|
|
180
|
+
const otherField = refField ? data.fields[refField.field] : undefined;
|
|
181
|
+
return useCalculatedControl(() => otherField?.value);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function useDataMatchExpression(
|
|
185
|
+
fvExpr: DataMatchExpression,
|
|
131
186
|
fields: SchemaField[],
|
|
132
187
|
data: Control<any>,
|
|
133
188
|
) {
|
|
@@ -139,9 +194,9 @@ function useFieldValueExpression(
|
|
|
139
194
|
});
|
|
140
195
|
}
|
|
141
196
|
|
|
142
|
-
function defaultEvalHooks(
|
|
197
|
+
export function defaultEvalHooks(
|
|
143
198
|
expr: EntityExpression,
|
|
144
|
-
context:
|
|
199
|
+
context: ControlDataContext,
|
|
145
200
|
) {
|
|
146
201
|
switch (expr.type) {
|
|
147
202
|
case ExpressionType.Jsonata:
|
|
@@ -149,9 +204,15 @@ function defaultEvalHooks(
|
|
|
149
204
|
(expr as JsonataExpression).expression,
|
|
150
205
|
context.groupControl,
|
|
151
206
|
);
|
|
152
|
-
case ExpressionType.
|
|
153
|
-
return
|
|
154
|
-
expr as
|
|
207
|
+
case ExpressionType.Data:
|
|
208
|
+
return useDataExpression(
|
|
209
|
+
expr as DataExpression,
|
|
210
|
+
context.fields,
|
|
211
|
+
context.groupControl,
|
|
212
|
+
);
|
|
213
|
+
case ExpressionType.DataMatch:
|
|
214
|
+
return useDataMatchExpression(
|
|
215
|
+
expr as DataMatchExpression,
|
|
155
216
|
context.fields,
|
|
156
217
|
context.groupControl,
|
|
157
218
|
);
|
|
@@ -164,12 +225,12 @@ export const defaultUseEvalExpressionHook =
|
|
|
164
225
|
makeEvalExpressionHook(defaultEvalHooks);
|
|
165
226
|
|
|
166
227
|
export function makeEvalExpressionHook(
|
|
167
|
-
f: (expr: EntityExpression, context:
|
|
228
|
+
f: (expr: EntityExpression, context: ControlDataContext) => Control<any>,
|
|
168
229
|
): (expr: EntityExpression | undefined) => EvalExpressionHook | undefined {
|
|
169
230
|
return (expr) => {
|
|
170
231
|
const r = useUpdatedRef(expr);
|
|
171
232
|
const cb = useCallback(
|
|
172
|
-
(ctx:
|
|
233
|
+
(ctx: ControlDataContext) => {
|
|
173
234
|
const expr = r.current!;
|
|
174
235
|
return f(expr, ctx);
|
|
175
236
|
},
|
|
@@ -191,7 +252,7 @@ export function useEvalDynamicHook(
|
|
|
191
252
|
}
|
|
192
253
|
|
|
193
254
|
export function matchesType(
|
|
194
|
-
context:
|
|
255
|
+
context: ControlDataContext,
|
|
195
256
|
types?: string[] | null,
|
|
196
257
|
) {
|
|
197
258
|
if (types == null || types.length === 0) return true;
|
|
@@ -199,11 +260,35 @@ export function matchesType(
|
|
|
199
260
|
return typeField && types.includes(typeField.value);
|
|
200
261
|
}
|
|
201
262
|
|
|
263
|
+
export function hideDisplayOnly(
|
|
264
|
+
context: ControlDataContext,
|
|
265
|
+
field: SchemaField,
|
|
266
|
+
definition: ControlDefinition,
|
|
267
|
+
schemaInterface: SchemaInterface,
|
|
268
|
+
) {
|
|
269
|
+
const displayOptions = getDisplayOnlyOptions(definition);
|
|
270
|
+
return (
|
|
271
|
+
displayOptions &&
|
|
272
|
+
!displayOptions.emptyText &&
|
|
273
|
+
schemaInterface.isEmptyValue(
|
|
274
|
+
field,
|
|
275
|
+
context.groupControl.fields[field.field].value,
|
|
276
|
+
)
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
202
280
|
export function useJsonataExpression(
|
|
203
281
|
jExpr: string,
|
|
204
282
|
data: Control<any>,
|
|
205
283
|
): Control<any> {
|
|
206
|
-
const compiledExpr = useMemo(() =>
|
|
284
|
+
const compiledExpr = useMemo(() => {
|
|
285
|
+
try {
|
|
286
|
+
return jsonata(jExpr);
|
|
287
|
+
} catch (e) {
|
|
288
|
+
console.error(e);
|
|
289
|
+
return jsonata("");
|
|
290
|
+
}
|
|
291
|
+
}, [jExpr]);
|
|
207
292
|
const control = useControl();
|
|
208
293
|
useControlEffect(
|
|
209
294
|
() => data.value,
|
package/src/index.ts
CHANGED
package/src/internal.ts
CHANGED
package/src/renderers.tsx
CHANGED
|
@@ -3,7 +3,6 @@ import React, {
|
|
|
3
3
|
Fragment,
|
|
4
4
|
ReactElement,
|
|
5
5
|
ReactNode,
|
|
6
|
-
useCallback,
|
|
7
6
|
useEffect,
|
|
8
7
|
useMemo,
|
|
9
8
|
useState,
|
|
@@ -14,6 +13,7 @@ import {
|
|
|
14
13
|
ActionRendererProps,
|
|
15
14
|
AdornmentProps,
|
|
16
15
|
AdornmentRenderer,
|
|
16
|
+
appendMarkupAt,
|
|
17
17
|
ArrayRendererProps,
|
|
18
18
|
ControlLayoutProps,
|
|
19
19
|
DataRendererProps,
|
|
@@ -22,18 +22,29 @@ import {
|
|
|
22
22
|
GroupRendererProps,
|
|
23
23
|
LabelRendererProps,
|
|
24
24
|
LabelType,
|
|
25
|
+
RenderedControl,
|
|
25
26
|
RenderedLayout,
|
|
26
27
|
renderLayoutParts,
|
|
27
|
-
|
|
28
|
+
VisibilityRendererProps,
|
|
28
29
|
} from "./controlRender";
|
|
29
30
|
import {
|
|
31
|
+
AdornmentPlacement,
|
|
32
|
+
ControlAdornment,
|
|
33
|
+
ControlAdornmentType,
|
|
30
34
|
DataRenderType,
|
|
31
35
|
DisplayDataType,
|
|
32
36
|
FieldOption,
|
|
33
37
|
FieldType,
|
|
38
|
+
FlexRenderer,
|
|
34
39
|
GridRenderer,
|
|
35
40
|
HtmlDisplay,
|
|
41
|
+
IconAdornment,
|
|
42
|
+
IconDisplay,
|
|
43
|
+
isDisplayOnlyRenderer,
|
|
44
|
+
isFlexRenderer,
|
|
36
45
|
isGridRenderer,
|
|
46
|
+
SchemaField,
|
|
47
|
+
SchemaInterface,
|
|
37
48
|
TextDisplay,
|
|
38
49
|
} from "./types";
|
|
39
50
|
import { hasOptions } from "./util";
|
|
@@ -53,7 +64,10 @@ export interface DefaultRenderers {
|
|
|
53
64
|
export interface LayoutRendererRegistration {
|
|
54
65
|
type: "layout";
|
|
55
66
|
match?: (props: ControlLayoutProps) => boolean;
|
|
56
|
-
render: (
|
|
67
|
+
render: (
|
|
68
|
+
props: ControlLayoutProps,
|
|
69
|
+
renderers: FormRenderer,
|
|
70
|
+
) => RenderedControl;
|
|
57
71
|
}
|
|
58
72
|
export interface DataRendererRegistration {
|
|
59
73
|
type: "data";
|
|
@@ -94,7 +108,10 @@ export interface ArrayRendererRegistration {
|
|
|
94
108
|
export interface GroupRendererRegistration {
|
|
95
109
|
type: "group";
|
|
96
110
|
renderType?: string | string[];
|
|
97
|
-
render: (
|
|
111
|
+
render: (
|
|
112
|
+
props: GroupRendererProps,
|
|
113
|
+
renderers: FormRenderer,
|
|
114
|
+
) => ReactElement | ((layout: ControlLayoutProps) => ControlLayoutProps);
|
|
98
115
|
}
|
|
99
116
|
|
|
100
117
|
export interface DisplayRendererRegistration {
|
|
@@ -114,10 +131,7 @@ export interface AdornmentRendererRegistration {
|
|
|
114
131
|
|
|
115
132
|
export interface VisibilityRendererRegistration {
|
|
116
133
|
type: "visibility";
|
|
117
|
-
render: (
|
|
118
|
-
visibility: Control<Visibility | undefined>,
|
|
119
|
-
children: () => ReactNode,
|
|
120
|
-
) => ReactNode;
|
|
134
|
+
render: (props: VisibilityRendererProps) => ReactNode;
|
|
121
135
|
}
|
|
122
136
|
|
|
123
137
|
export type RendererRegistration =
|
|
@@ -219,12 +233,16 @@ export function createFormRenderer(
|
|
|
219
233
|
return (l) => ({ ...l, children: result });
|
|
220
234
|
}
|
|
221
235
|
|
|
222
|
-
function renderGroup(
|
|
236
|
+
function renderGroup(
|
|
237
|
+
props: GroupRendererProps,
|
|
238
|
+
): (layout: ControlLayoutProps) => ControlLayoutProps {
|
|
223
239
|
const renderType = props.renderOptions.type;
|
|
224
240
|
const renderer =
|
|
225
241
|
groupRegistrations.find((x) => isOneOf(x.renderType, renderType)) ??
|
|
226
242
|
defaultRenderers.group;
|
|
227
|
-
|
|
243
|
+
const result = renderer.render(props, formRenderers);
|
|
244
|
+
if (typeof result === "function") return result;
|
|
245
|
+
return (l) => ({ ...l, children: result });
|
|
228
246
|
}
|
|
229
247
|
|
|
230
248
|
function renderAction(props: ActionRendererProps) {
|
|
@@ -364,6 +382,8 @@ interface DefaultGroupRendererOptions {
|
|
|
364
382
|
gridStyles?: (columns: GridRenderer) => StyleProps;
|
|
365
383
|
gridClassName?: string;
|
|
366
384
|
defaultGridColumns?: number;
|
|
385
|
+
flexClassName?: string;
|
|
386
|
+
defaultFlexGap?: string;
|
|
367
387
|
}
|
|
368
388
|
|
|
369
389
|
export function createDefaultGroupRenderer(
|
|
@@ -375,6 +395,8 @@ export function createDefaultGroupRenderer(
|
|
|
375
395
|
defaultGridColumns = 2,
|
|
376
396
|
gridClassName,
|
|
377
397
|
standardClassName,
|
|
398
|
+
flexClassName,
|
|
399
|
+
defaultFlexGap,
|
|
378
400
|
} = options ?? {};
|
|
379
401
|
|
|
380
402
|
function defaultGridStyles({
|
|
@@ -389,17 +411,38 @@ export function createDefaultGroupRenderer(
|
|
|
389
411
|
};
|
|
390
412
|
}
|
|
391
413
|
|
|
414
|
+
function flexStyles(options: FlexRenderer): StyleProps {
|
|
415
|
+
return {
|
|
416
|
+
className: flexClassName,
|
|
417
|
+
style: {
|
|
418
|
+
display: "flex",
|
|
419
|
+
gap: options.gap ? options.gap : defaultFlexGap,
|
|
420
|
+
flexDirection: options.direction
|
|
421
|
+
? (options.direction as any)
|
|
422
|
+
: undefined,
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
392
427
|
function render(props: GroupRendererProps) {
|
|
393
428
|
const { childCount, renderChild, renderOptions } = props;
|
|
394
429
|
|
|
395
430
|
const { style, className: gcn } = isGridRenderer(renderOptions)
|
|
396
431
|
? gridStyles(renderOptions)
|
|
397
|
-
: (
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
432
|
+
: isFlexRenderer(renderOptions)
|
|
433
|
+
? flexStyles(renderOptions)
|
|
434
|
+
: ({ className: standardClassName } as StyleProps);
|
|
435
|
+
|
|
436
|
+
return (cp: ControlLayoutProps) => {
|
|
437
|
+
return {
|
|
438
|
+
...cp,
|
|
439
|
+
children: (
|
|
440
|
+
<div className={clsx(props.className, className, gcn)} style={style}>
|
|
441
|
+
{Array.from({ length: childCount }, (_, x) => renderChild(x))}
|
|
442
|
+
</div>
|
|
443
|
+
),
|
|
444
|
+
};
|
|
445
|
+
};
|
|
403
446
|
}
|
|
404
447
|
return { type: "group", render };
|
|
405
448
|
}
|
|
@@ -412,37 +455,57 @@ export function createDefaultDisplayRenderer(
|
|
|
412
455
|
options: DefaultDisplayRendererOptions = {},
|
|
413
456
|
): DisplayRendererRegistration {
|
|
414
457
|
return {
|
|
415
|
-
render: (
|
|
416
|
-
switch (data.type) {
|
|
417
|
-
case DisplayDataType.Text:
|
|
418
|
-
return (
|
|
419
|
-
<div className={options.textClassName}>
|
|
420
|
-
{(data as TextDisplay).text}
|
|
421
|
-
</div>
|
|
422
|
-
);
|
|
423
|
-
case DisplayDataType.Html:
|
|
424
|
-
return (
|
|
425
|
-
<div
|
|
426
|
-
className={options.htmlClassName}
|
|
427
|
-
dangerouslySetInnerHTML={{
|
|
428
|
-
__html: (data as HtmlDisplay).html,
|
|
429
|
-
}}
|
|
430
|
-
/>
|
|
431
|
-
);
|
|
432
|
-
default:
|
|
433
|
-
return <h1>Unknown display type: {data.type}</h1>;
|
|
434
|
-
}
|
|
435
|
-
},
|
|
458
|
+
render: (props) => <DefaultDisplay {...options} {...props} />,
|
|
436
459
|
type: "display",
|
|
437
460
|
};
|
|
438
461
|
}
|
|
439
462
|
|
|
463
|
+
export function DefaultDisplay({
|
|
464
|
+
data,
|
|
465
|
+
display,
|
|
466
|
+
className,
|
|
467
|
+
style,
|
|
468
|
+
...options
|
|
469
|
+
}: DefaultDisplayRendererOptions & DisplayRendererProps) {
|
|
470
|
+
switch (data.type) {
|
|
471
|
+
case DisplayDataType.Icon:
|
|
472
|
+
return (
|
|
473
|
+
<i
|
|
474
|
+
style={style}
|
|
475
|
+
className={clsx(
|
|
476
|
+
className,
|
|
477
|
+
display ? display.value : (data as IconDisplay).iconClass,
|
|
478
|
+
)}
|
|
479
|
+
/>
|
|
480
|
+
);
|
|
481
|
+
case DisplayDataType.Text:
|
|
482
|
+
return (
|
|
483
|
+
<div style={style} className={clsx(className, options.textClassName)}>
|
|
484
|
+
{display ? display.value : (data as TextDisplay).text}
|
|
485
|
+
</div>
|
|
486
|
+
);
|
|
487
|
+
case DisplayDataType.Html:
|
|
488
|
+
return (
|
|
489
|
+
<div
|
|
490
|
+
style={style}
|
|
491
|
+
className={clsx(className, options.htmlClassName)}
|
|
492
|
+
dangerouslySetInnerHTML={{
|
|
493
|
+
__html: display ? display.value ?? "" : (data as HtmlDisplay).html,
|
|
494
|
+
}}
|
|
495
|
+
/>
|
|
496
|
+
);
|
|
497
|
+
default:
|
|
498
|
+
return <h1>Unknown display type: {data.type}</h1>;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
440
502
|
export const DefaultBoolOptions: FieldOption[] = [
|
|
441
503
|
{ name: "Yes", value: true },
|
|
442
504
|
{ name: "No", value: false },
|
|
443
505
|
];
|
|
444
506
|
interface DefaultDataRendererOptions {
|
|
445
507
|
inputClass?: string;
|
|
508
|
+
displayOnlyClass?: string;
|
|
446
509
|
selectOptions?: SelectRendererOptions;
|
|
447
510
|
booleanOptions?: FieldOption[];
|
|
448
511
|
optionRenderer?: DataRendererRegistration;
|
|
@@ -452,7 +515,7 @@ export function createDefaultDataRenderer(
|
|
|
452
515
|
options: DefaultDataRendererOptions = {},
|
|
453
516
|
): DataRendererRegistration {
|
|
454
517
|
const selectRenderer = createSelectRenderer(options.selectOptions ?? {});
|
|
455
|
-
const { inputClass, booleanOptions, optionRenderer } = {
|
|
518
|
+
const { inputClass, booleanOptions, optionRenderer, displayOnlyClass } = {
|
|
456
519
|
optionRenderer: selectRenderer,
|
|
457
520
|
booleanOptions: DefaultBoolOptions,
|
|
458
521
|
...options,
|
|
@@ -461,9 +524,25 @@ export function createDefaultDataRenderer(
|
|
|
461
524
|
if (asArray) {
|
|
462
525
|
return asArray();
|
|
463
526
|
}
|
|
464
|
-
|
|
527
|
+
const renderOptions = props.renderOptions;
|
|
528
|
+
let renderType = renderOptions.type;
|
|
465
529
|
const fieldType = props.field.type;
|
|
466
530
|
if (fieldType == FieldType.Any) return <>No control for Any</>;
|
|
531
|
+
if (isDisplayOnlyRenderer(renderOptions))
|
|
532
|
+
return (p) => ({
|
|
533
|
+
...p,
|
|
534
|
+
className: displayOnlyClass,
|
|
535
|
+
children: (
|
|
536
|
+
<DefaultDisplayOnly
|
|
537
|
+
field={props.field}
|
|
538
|
+
schemaInterface={props.dataContext.schemaInterface}
|
|
539
|
+
control={props.control}
|
|
540
|
+
className={props.className}
|
|
541
|
+
style={props.style}
|
|
542
|
+
emptyText={renderOptions.emptyText}
|
|
543
|
+
/>
|
|
544
|
+
),
|
|
545
|
+
});
|
|
467
546
|
const isBool = fieldType === FieldType.Bool;
|
|
468
547
|
if (booleanOptions != null && isBool && props.options == null) {
|
|
469
548
|
return renderers.renderData(
|
|
@@ -479,10 +558,15 @@ export function createDefaultDataRenderer(
|
|
|
479
558
|
return selectRenderer.render(props, undefined, renderers);
|
|
480
559
|
}
|
|
481
560
|
return renderType === DataRenderType.Checkbox ? (
|
|
482
|
-
<Fcheckbox
|
|
561
|
+
<Fcheckbox
|
|
562
|
+
style={props.style}
|
|
563
|
+
className={props.className}
|
|
564
|
+
control={props.control}
|
|
565
|
+
/>
|
|
483
566
|
) : (
|
|
484
567
|
<ControlInput
|
|
485
|
-
className={inputClass}
|
|
568
|
+
className={clsx(props.className, inputClass)}
|
|
569
|
+
style={props.style}
|
|
486
570
|
id={props.id}
|
|
487
571
|
readOnly={props.readonly}
|
|
488
572
|
control={props.control}
|
|
@@ -492,6 +576,33 @@ export function createDefaultDataRenderer(
|
|
|
492
576
|
});
|
|
493
577
|
}
|
|
494
578
|
|
|
579
|
+
export function DefaultDisplayOnly({
|
|
580
|
+
control,
|
|
581
|
+
className,
|
|
582
|
+
emptyText,
|
|
583
|
+
schemaInterface,
|
|
584
|
+
field,
|
|
585
|
+
style,
|
|
586
|
+
}: {
|
|
587
|
+
control: Control<any>;
|
|
588
|
+
field: SchemaField;
|
|
589
|
+
schemaInterface: SchemaInterface;
|
|
590
|
+
className?: string;
|
|
591
|
+
style?: React.CSSProperties;
|
|
592
|
+
emptyText?: string | null;
|
|
593
|
+
}) {
|
|
594
|
+
const v = control.value;
|
|
595
|
+
const text =
|
|
596
|
+
(schemaInterface.isEmptyValue(field, v)
|
|
597
|
+
? emptyText
|
|
598
|
+
: schemaInterface.textValue(field, v)) ?? "";
|
|
599
|
+
return (
|
|
600
|
+
<div style={style} className={className}>
|
|
601
|
+
{text}
|
|
602
|
+
</div>
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
|
|
495
606
|
export function ControlInput({
|
|
496
607
|
control,
|
|
497
608
|
convert,
|
|
@@ -522,7 +633,18 @@ export function createDefaultAdornmentRenderer(
|
|
|
522
633
|
): AdornmentRendererRegistration {
|
|
523
634
|
return {
|
|
524
635
|
type: "adornment",
|
|
525
|
-
render: ({ adornment }) => ({
|
|
636
|
+
render: ({ adornment }) => ({
|
|
637
|
+
apply: (rl) => {
|
|
638
|
+
if (isIconAdornment(adornment)) {
|
|
639
|
+
return appendMarkupAt(
|
|
640
|
+
adornment.placement ?? AdornmentPlacement.ControlStart,
|
|
641
|
+
<i className={adornment.iconClass} />,
|
|
642
|
+
)(rl);
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
priority: 0,
|
|
646
|
+
adornment,
|
|
647
|
+
}),
|
|
526
648
|
};
|
|
527
649
|
}
|
|
528
650
|
|
|
@@ -562,12 +684,19 @@ function createDefaultLayoutRenderer(
|
|
|
562
684
|
options: DefaultLayoutRendererOptions = {},
|
|
563
685
|
) {
|
|
564
686
|
return createLayoutRenderer((props, renderers) => {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
{...options}
|
|
569
|
-
/>
|
|
687
|
+
const layout = renderLayoutParts(
|
|
688
|
+
{ ...props, className: clsx(props.className, options.className) },
|
|
689
|
+
renderers,
|
|
570
690
|
);
|
|
691
|
+
return {
|
|
692
|
+
children: <DefaultLayout layout={layout} {...options} />,
|
|
693
|
+
className: layout.className,
|
|
694
|
+
style: layout.style,
|
|
695
|
+
divRef: (e) =>
|
|
696
|
+
e && props.errorControl
|
|
697
|
+
? (props.errorControl.meta.scrollElement = e)
|
|
698
|
+
: undefined,
|
|
699
|
+
};
|
|
571
700
|
});
|
|
572
701
|
}
|
|
573
702
|
|
|
@@ -639,6 +768,10 @@ function isOneOf<A>(x: A | A[] | undefined, v: A) {
|
|
|
639
768
|
return x == null ? true : Array.isArray(x) ? x.includes(v) : v === x;
|
|
640
769
|
}
|
|
641
770
|
|
|
771
|
+
export function isIconAdornment(a: ControlAdornment): a is IconAdornment {
|
|
772
|
+
return a.type === ControlAdornmentType.Icon;
|
|
773
|
+
}
|
|
774
|
+
|
|
642
775
|
export function createLayoutRenderer(
|
|
643
776
|
render: LayoutRendererRegistration["render"],
|
|
644
777
|
options?: Partial<LayoutRendererRegistration>,
|
|
@@ -691,7 +824,7 @@ export function createSelectRenderer(options: SelectRendererOptions = {}) {
|
|
|
691
824
|
return createDataRenderer(
|
|
692
825
|
(props, asArray) => (
|
|
693
826
|
<SelectDataRenderer
|
|
694
|
-
className={options.className}
|
|
827
|
+
className={clsx(props.className, options.className)}
|
|
695
828
|
state={props.control}
|
|
696
829
|
id={props.id}
|
|
697
830
|
options={props.options!}
|
|
@@ -795,49 +928,47 @@ export function createInputConversion(ft: string): InputConversion {
|
|
|
795
928
|
}
|
|
796
929
|
|
|
797
930
|
export function createDefaultVisibilityRenderer() {
|
|
798
|
-
return createVisibilityRenderer((
|
|
799
|
-
<DefaultVisibility visibility={cv} children={ch} />
|
|
800
|
-
));
|
|
931
|
+
return createVisibilityRenderer((props) => <DefaultVisibility {...props} />);
|
|
801
932
|
}
|
|
802
933
|
|
|
803
934
|
export function DefaultVisibility({
|
|
804
935
|
visibility,
|
|
805
936
|
children,
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
}) {
|
|
937
|
+
className,
|
|
938
|
+
style,
|
|
939
|
+
divRef,
|
|
940
|
+
}: VisibilityRendererProps) {
|
|
810
941
|
const v = visibility.value;
|
|
811
942
|
useEffect(() => {
|
|
812
943
|
if (v) {
|
|
813
944
|
visibility.setValue((ex) => ({ visible: v.visible, showing: v.visible }));
|
|
814
945
|
}
|
|
815
946
|
}, [v?.visible]);
|
|
816
|
-
return v?.visible ?
|
|
947
|
+
return v?.visible ? (
|
|
948
|
+
<div className={clsx(className)} style={style} ref={divRef}>
|
|
949
|
+
{children}
|
|
950
|
+
</div>
|
|
951
|
+
) : (
|
|
952
|
+
<></>
|
|
953
|
+
);
|
|
817
954
|
}
|
|
818
955
|
|
|
819
956
|
export function DefaultLayout({
|
|
820
|
-
className,
|
|
821
957
|
errorClass,
|
|
958
|
+
className,
|
|
822
959
|
layout: { controlEnd, controlStart, label, children, errorControl },
|
|
823
960
|
}: DefaultLayoutRendererOptions & {
|
|
824
961
|
layout: RenderedLayout;
|
|
825
962
|
}) {
|
|
826
963
|
const ec = errorControl;
|
|
827
964
|
const errorText = ec && ec.touched ? ec.error : undefined;
|
|
828
|
-
const refCb = useCallback(
|
|
829
|
-
(e: HTMLDivElement | null) => {
|
|
830
|
-
if (ec) ec.meta.scrollElement = e;
|
|
831
|
-
},
|
|
832
|
-
[ec],
|
|
833
|
-
);
|
|
834
965
|
return (
|
|
835
|
-
|
|
966
|
+
<>
|
|
836
967
|
{label}
|
|
837
968
|
{controlStart}
|
|
838
969
|
{children}
|
|
839
970
|
{errorText && <div className={errorClass}>{errorText}</div>}
|
|
840
971
|
{controlEnd}
|
|
841
|
-
|
|
972
|
+
</>
|
|
842
973
|
);
|
|
843
974
|
}
|