@react-typed-forms/schemas 7.3.2 → 8.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 +6 -0
- package/lib/controlRender.d.ts +13 -8
- package/lib/index.js +150 -72
- package/lib/index.js.map +1 -1
- package/lib/schemaBuilder.d.ts +1 -0
- package/lib/util.d.ts +1 -0
- package/package.json +1 -1
- package/src/controlBuilder.ts +46 -1
- package/src/controlRender.tsx +53 -38
- package/src/hooks.tsx +3 -2
- package/src/renderers.tsx +5 -8
- package/src/schemaBuilder.ts +25 -0
- package/src/util.ts +12 -0
package/lib/schemaBuilder.d.ts
CHANGED
|
@@ -87,4 +87,5 @@ export declare function defaultScalarField(field: string, displayName: string):
|
|
|
87
87
|
export declare function defaultCompoundField(field: string, displayName: string, collection: boolean): CompoundField & {
|
|
88
88
|
type: FieldType.Compound;
|
|
89
89
|
};
|
|
90
|
+
export declare function mergeField(field: SchemaField, mergeInto: SchemaField[]): SchemaField[];
|
|
90
91
|
export {};
|
package/lib/util.d.ts
CHANGED
|
@@ -39,3 +39,4 @@ export declare function cleanDataForSchema(v: {
|
|
|
39
39
|
} | undefined, fields: SchemaField[]): any;
|
|
40
40
|
export declare function getAllReferencedClasses(c: ControlDefinition): string[];
|
|
41
41
|
export declare function jsonPathString(jsonPath: JsonPath[]): string;
|
|
42
|
+
export declare function findChildDefinition(parent: ControlDefinition, childPath: number | number[]): ControlDefinition;
|
package/package.json
CHANGED
package/src/controlBuilder.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CompoundField,
|
|
2
3
|
ControlDefinition,
|
|
3
4
|
ControlDefinitionType,
|
|
4
5
|
DataControlDefinition,
|
|
@@ -18,7 +19,8 @@ import {
|
|
|
18
19
|
} from "./types";
|
|
19
20
|
import { ActionRendererProps } from "./controlRender";
|
|
20
21
|
import { useMemo } from "react";
|
|
21
|
-
import { addMissingControls } from "./util";
|
|
22
|
+
import { addMissingControls, isCompoundField } from "./util";
|
|
23
|
+
import { mergeField } from "./schemaBuilder";
|
|
22
24
|
|
|
23
25
|
export function dataControl(
|
|
24
26
|
field: string,
|
|
@@ -128,3 +130,46 @@ export function useControlDefinitionForSchema(
|
|
|
128
130
|
[sf, definition],
|
|
129
131
|
);
|
|
130
132
|
}
|
|
133
|
+
|
|
134
|
+
export interface CustomRenderOptions {
|
|
135
|
+
value: string;
|
|
136
|
+
name: string;
|
|
137
|
+
fields: SchemaField[];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function addCustomDataRenderOptions(
|
|
141
|
+
controlFields: SchemaField[],
|
|
142
|
+
customRenderOptions: CustomRenderOptions[],
|
|
143
|
+
): SchemaField[] {
|
|
144
|
+
return controlFields.map((x) =>
|
|
145
|
+
x.field === "renderOptions" && isCompoundField(x) ? addRenderOptions(x) : x,
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
function addRenderOptions(roField: CompoundField): CompoundField {
|
|
149
|
+
const children = roField.children;
|
|
150
|
+
const withTypes = children.map((x) =>
|
|
151
|
+
x.field === "type" ? addRenderOptionType(x) : x,
|
|
152
|
+
);
|
|
153
|
+
return {
|
|
154
|
+
...roField,
|
|
155
|
+
children: customRenderOptions.reduce(
|
|
156
|
+
(renderOptionFields, ro) =>
|
|
157
|
+
ro.fields
|
|
158
|
+
.map((x) => ({ ...x, onlyForTypes: [ro.value] }))
|
|
159
|
+
.reduce((af, x) => mergeField(x, af), renderOptionFields),
|
|
160
|
+
withTypes,
|
|
161
|
+
),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function addRenderOptionType(typeField: SchemaField): SchemaField {
|
|
166
|
+
const options = typeField.options ?? [];
|
|
167
|
+
return {
|
|
168
|
+
...typeField,
|
|
169
|
+
options: [
|
|
170
|
+
...options,
|
|
171
|
+
...customRenderOptions.map(({ name, value }) => ({ name, value })),
|
|
172
|
+
],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
package/src/controlRender.tsx
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
DisplayData,
|
|
27
27
|
DynamicPropertyType,
|
|
28
28
|
FieldOption,
|
|
29
|
+
GroupedControlsDefinition,
|
|
29
30
|
GroupRenderOptions,
|
|
30
31
|
isActionControlsDefinition,
|
|
31
32
|
isDataControlDefinition,
|
|
@@ -39,6 +40,7 @@ import {
|
|
|
39
40
|
ControlDataContext,
|
|
40
41
|
elementValueForField,
|
|
41
42
|
fieldDisplayName,
|
|
43
|
+
findChildDefinition,
|
|
42
44
|
findField,
|
|
43
45
|
isCompoundField,
|
|
44
46
|
useUpdatedRef,
|
|
@@ -160,15 +162,14 @@ export interface DisplayRendererProps {
|
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
export interface GroupRendererProps {
|
|
165
|
+
children: ControlDefinition[];
|
|
163
166
|
renderOptions: GroupRenderOptions;
|
|
164
|
-
|
|
165
|
-
renderChild: (child: number) => ReactNode;
|
|
167
|
+
renderChild: ChildRenderer;
|
|
166
168
|
className?: string;
|
|
167
169
|
style?: React.CSSProperties;
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
export interface DataRendererProps {
|
|
171
|
-
definition: DataControlDefinition;
|
|
172
173
|
renderOptions: RenderOptions;
|
|
173
174
|
field: SchemaField;
|
|
174
175
|
id: string;
|
|
@@ -180,7 +181,7 @@ export interface DataRendererProps {
|
|
|
180
181
|
className?: string;
|
|
181
182
|
style?: React.CSSProperties;
|
|
182
183
|
dataContext: ControlDataContext;
|
|
183
|
-
|
|
184
|
+
children: ControlDefinition[];
|
|
184
185
|
renderChild: ChildRenderer;
|
|
185
186
|
toArrayProps?: () => ArrayRendererProps;
|
|
186
187
|
}
|
|
@@ -211,7 +212,6 @@ export interface DataControlProps {
|
|
|
211
212
|
control: Control<any>;
|
|
212
213
|
options: FormContextOptions;
|
|
213
214
|
style: React.CSSProperties | undefined;
|
|
214
|
-
childCount: number;
|
|
215
215
|
renderChild: ChildRenderer;
|
|
216
216
|
allowedOptions?: Control<any[] | undefined>;
|
|
217
217
|
elementRenderer?: (elemIndex: number) => ReactNode;
|
|
@@ -343,13 +343,7 @@ export function useControlRenderer(
|
|
|
343
343
|
!!myOptions.hidden,
|
|
344
344
|
parentDataContext,
|
|
345
345
|
);
|
|
346
|
-
const
|
|
347
|
-
c.children?.map((cd) =>
|
|
348
|
-
useControlRenderer(cd, controlDataContext.fields, renderer, {
|
|
349
|
-
...options,
|
|
350
|
-
...myOptions,
|
|
351
|
-
}),
|
|
352
|
-
) ?? [];
|
|
346
|
+
const childOptions: ControlRenderOptions = { ...options, ...myOptions };
|
|
353
347
|
|
|
354
348
|
useEffect(() => {
|
|
355
349
|
if (control && typeof myOptions.disabled === "boolean")
|
|
@@ -364,11 +358,21 @@ export function useControlRenderer(
|
|
|
364
358
|
const labelAndChildren = renderControlLayout({
|
|
365
359
|
definition: c,
|
|
366
360
|
renderer,
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
361
|
+
renderChild: (k, child, path) => (
|
|
362
|
+
<ControlRenderer
|
|
363
|
+
key={k}
|
|
364
|
+
control={controlDataContext.data}
|
|
365
|
+
fields={controlDataContext.fields}
|
|
366
|
+
definition={findChildDefinition(c, child)}
|
|
367
|
+
parentPath={
|
|
368
|
+
path
|
|
369
|
+
? [...controlDataContext.path, ...path]
|
|
370
|
+
: controlDataContext.path
|
|
371
|
+
}
|
|
372
|
+
renderer={renderer}
|
|
373
|
+
options={childOptions}
|
|
374
|
+
/>
|
|
375
|
+
),
|
|
372
376
|
createDataProps: dataProps,
|
|
373
377
|
formOptions: myOptions,
|
|
374
378
|
dataContext: controlDataContext,
|
|
@@ -445,19 +449,36 @@ export function getControlData(
|
|
|
445
449
|
];
|
|
446
450
|
}
|
|
447
451
|
|
|
452
|
+
export function ControlRenderer({
|
|
453
|
+
definition,
|
|
454
|
+
fields,
|
|
455
|
+
renderer,
|
|
456
|
+
options,
|
|
457
|
+
control,
|
|
458
|
+
parentPath,
|
|
459
|
+
}: {
|
|
460
|
+
definition: ControlDefinition;
|
|
461
|
+
fields: SchemaField[];
|
|
462
|
+
renderer: FormRenderer;
|
|
463
|
+
options?: ControlRenderOptions;
|
|
464
|
+
control: Control<any>;
|
|
465
|
+
parentPath?: JsonPath[];
|
|
466
|
+
}) {
|
|
467
|
+
const Render = useControlRenderer(definition, fields, renderer, options);
|
|
468
|
+
return <Render control={control} parentPath={parentPath} />;
|
|
469
|
+
}
|
|
470
|
+
|
|
448
471
|
function groupProps(
|
|
449
|
-
|
|
450
|
-
childCount: number,
|
|
472
|
+
definition: GroupedControlsDefinition,
|
|
451
473
|
renderChild: ChildRenderer,
|
|
452
474
|
data: DataContext,
|
|
453
475
|
className: string | null | undefined,
|
|
454
476
|
style: React.CSSProperties | undefined,
|
|
455
477
|
): GroupRendererProps {
|
|
456
478
|
return {
|
|
457
|
-
|
|
458
|
-
renderChild
|
|
459
|
-
|
|
460
|
-
renderOptions,
|
|
479
|
+
children: definition.children ?? [],
|
|
480
|
+
renderChild,
|
|
481
|
+
renderOptions: definition.groupOptions ?? { type: "Standard" },
|
|
461
482
|
className: cc(className),
|
|
462
483
|
style,
|
|
463
484
|
};
|
|
@@ -479,7 +500,7 @@ export function defaultDataProps({
|
|
|
479
500
|
(field.options?.length ?? 0) === 0 ? null : field.options;
|
|
480
501
|
const allowed = allowedOptions?.value ?? [];
|
|
481
502
|
return {
|
|
482
|
-
definition,
|
|
503
|
+
children: definition.children ?? [],
|
|
483
504
|
control,
|
|
484
505
|
field,
|
|
485
506
|
id: "c" + control.uniqueId,
|
|
@@ -541,14 +562,13 @@ export function defaultArrayProps(
|
|
|
541
562
|
|
|
542
563
|
export type ChildRenderer = (
|
|
543
564
|
k: Key,
|
|
544
|
-
|
|
545
|
-
|
|
565
|
+
child: number | number[],
|
|
566
|
+
parentPath?: JsonPath[],
|
|
546
567
|
) => ReactNode;
|
|
547
568
|
|
|
548
569
|
export interface RenderControlProps {
|
|
549
570
|
definition: ControlDefinition;
|
|
550
571
|
renderer: FormRenderer;
|
|
551
|
-
childCount: number;
|
|
552
572
|
renderChild: ChildRenderer;
|
|
553
573
|
createDataProps: CreateDataProps;
|
|
554
574
|
formOptions: FormContextOptions;
|
|
@@ -562,7 +582,6 @@ export interface RenderControlProps {
|
|
|
562
582
|
export function renderControlLayout({
|
|
563
583
|
definition: c,
|
|
564
584
|
renderer,
|
|
565
|
-
childCount,
|
|
566
585
|
renderChild: childRenderer,
|
|
567
586
|
control: childControl,
|
|
568
587
|
schemaField,
|
|
@@ -587,14 +606,7 @@ export function renderControlLayout({
|
|
|
587
606
|
}
|
|
588
607
|
return {
|
|
589
608
|
processLayout: renderer.renderGroup(
|
|
590
|
-
groupProps(
|
|
591
|
-
c.groupOptions,
|
|
592
|
-
childCount,
|
|
593
|
-
childRenderer,
|
|
594
|
-
dataContext,
|
|
595
|
-
c.styleClass,
|
|
596
|
-
style,
|
|
597
|
-
),
|
|
609
|
+
groupProps(c, childRenderer, dataContext, c.styleClass, style),
|
|
598
610
|
),
|
|
599
611
|
label: {
|
|
600
612
|
label: c.title,
|
|
@@ -640,9 +652,12 @@ export function renderControlLayout({
|
|
|
640
652
|
elemIndex != null ? childControl!.elements[elemIndex] : childControl,
|
|
641
653
|
options: dataOptions,
|
|
642
654
|
style,
|
|
643
|
-
childCount,
|
|
644
655
|
allowedOptions,
|
|
645
|
-
renderChild:
|
|
656
|
+
renderChild:
|
|
657
|
+
elemIndex != null
|
|
658
|
+
? (k, d, p) =>
|
|
659
|
+
childRenderer(k, d, p ? [elemIndex, ...p] : [elemIndex])
|
|
660
|
+
: childRenderer,
|
|
646
661
|
elementRenderer:
|
|
647
662
|
elemIndex == null && schemaField.collection
|
|
648
663
|
? (ei) => renderLayoutParts(renderData(c, ei), renderer).children
|
package/src/hooks.tsx
CHANGED
|
@@ -307,14 +307,15 @@ export function useJsonataExpression(
|
|
|
307
307
|
bindings?: () => Record<string, any>,
|
|
308
308
|
): Control<any> {
|
|
309
309
|
const pathString = jsonPathString(dataContext.path);
|
|
310
|
+
const fullExpr = pathString ? pathString + ".(" + jExpr + ")" : jExpr;
|
|
310
311
|
const compiledExpr = useMemo(() => {
|
|
311
312
|
try {
|
|
312
|
-
return jsonata(
|
|
313
|
+
return jsonata(fullExpr);
|
|
313
314
|
} catch (e) {
|
|
314
315
|
console.error(e);
|
|
315
316
|
return jsonata("null");
|
|
316
317
|
}
|
|
317
|
-
}, [
|
|
318
|
+
}, [fullExpr]);
|
|
318
319
|
const control = useControl();
|
|
319
320
|
const listenerRef = useRef<() => void>();
|
|
320
321
|
const [ref] = useRefState(() =>
|
package/src/renderers.tsx
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
AdornmentPlacement,
|
|
32
32
|
ControlAdornment,
|
|
33
33
|
ControlAdornmentType,
|
|
34
|
+
ControlDefinitionType,
|
|
34
35
|
DataRenderType,
|
|
35
36
|
DisplayDataType,
|
|
36
37
|
FieldOption,
|
|
@@ -423,7 +424,7 @@ export function createDefaultGroupRenderer(
|
|
|
423
424
|
}
|
|
424
425
|
|
|
425
426
|
function render(props: GroupRendererProps) {
|
|
426
|
-
const {
|
|
427
|
+
const { renderChild, renderOptions, children } = props;
|
|
427
428
|
|
|
428
429
|
const { style, className: gcn } = isGridRenderer(renderOptions)
|
|
429
430
|
? gridStyles(renderOptions)
|
|
@@ -436,7 +437,7 @@ export function createDefaultGroupRenderer(
|
|
|
436
437
|
...cp,
|
|
437
438
|
children: (
|
|
438
439
|
<div className={clsx(props.className, className, gcn)} style={style}>
|
|
439
|
-
{
|
|
440
|
+
{children?.map((c, i) => renderChild(i, i))}
|
|
440
441
|
</div>
|
|
441
442
|
),
|
|
442
443
|
};
|
|
@@ -530,13 +531,9 @@ export function createDefaultDataRenderer(
|
|
|
530
531
|
return renderers.renderGroup({
|
|
531
532
|
style: props.style,
|
|
532
533
|
className: props.className,
|
|
534
|
+
children: props.children,
|
|
533
535
|
renderOptions: { type: "Standard", hideTitle: true },
|
|
534
|
-
renderChild:
|
|
535
|
-
props.renderChild(i, i, {
|
|
536
|
-
control: props.dataContext.data,
|
|
537
|
-
parentPath: props.dataContext.path,
|
|
538
|
-
}),
|
|
539
|
-
childCount: props.childCount,
|
|
536
|
+
renderChild: props.renderChild,
|
|
540
537
|
});
|
|
541
538
|
}
|
|
542
539
|
const renderOptions = props.renderOptions;
|
package/src/schemaBuilder.ts
CHANGED
|
@@ -144,3 +144,28 @@ export function defaultCompoundField(
|
|
|
144
144
|
children: [],
|
|
145
145
|
};
|
|
146
146
|
}
|
|
147
|
+
|
|
148
|
+
export function mergeField(
|
|
149
|
+
field: SchemaField,
|
|
150
|
+
mergeInto: SchemaField[],
|
|
151
|
+
): SchemaField[] {
|
|
152
|
+
const existing = mergeInto.find((x) => x.field === field.field);
|
|
153
|
+
if (existing) {
|
|
154
|
+
return mergeInto.map((x) =>
|
|
155
|
+
x !== existing
|
|
156
|
+
? x
|
|
157
|
+
: {
|
|
158
|
+
...x,
|
|
159
|
+
onlyForTypes: mergeTypes(x.onlyForTypes, field.onlyForTypes),
|
|
160
|
+
},
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
return [...mergeInto, field];
|
|
164
|
+
|
|
165
|
+
function mergeTypes(f?: string[] | null, s?: string[] | null) {
|
|
166
|
+
if (!f) return s;
|
|
167
|
+
if (!s) return f;
|
|
168
|
+
const extras = s.filter((x) => !f.includes(x));
|
|
169
|
+
return extras.length ? [...f, ...extras] : f;
|
|
170
|
+
}
|
|
171
|
+
}
|
package/src/util.ts
CHANGED
|
@@ -408,3 +408,15 @@ export function jsonPathString(jsonPath: JsonPath[]) {
|
|
|
408
408
|
});
|
|
409
409
|
return out;
|
|
410
410
|
}
|
|
411
|
+
|
|
412
|
+
export function findChildDefinition(
|
|
413
|
+
parent: ControlDefinition,
|
|
414
|
+
childPath: number | number[],
|
|
415
|
+
): ControlDefinition {
|
|
416
|
+
if (Array.isArray(childPath)) {
|
|
417
|
+
let base = parent;
|
|
418
|
+
childPath.forEach((x) => (base = base.children![x]));
|
|
419
|
+
return base;
|
|
420
|
+
}
|
|
421
|
+
return parent.children![childPath];
|
|
422
|
+
}
|