@react-typed-forms/schemas 7.2.0 → 7.3.1
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 +2 -31
- package/lib/controlRender.d.ts +10 -4
- package/lib/hooks.d.ts +2 -1
- package/lib/index.js +172 -72
- package/lib/index.js.map +1 -1
- package/lib/internal.d.ts +2 -1
- package/lib/util.d.ts +4 -3
- package/package.json +2 -2
- package/src/controlRender.tsx +94 -71
- package/src/hooks.tsx +57 -26
- package/src/internal.ts +38 -1
- package/src/renderers.tsx +7 -3
- package/src/util.ts +31 -7
- package/src/validators.ts +1 -5
package/lib/internal.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import { Control } from "@react-typed-forms/core";
|
|
1
|
+
import { ChangeListenerFunc, Control } from "@react-typed-forms/core";
|
|
2
2
|
export declare function useCalculatedControl<V>(calculate: () => V): Control<V>;
|
|
3
3
|
export declare function cc(n: string | null | undefined): string | undefined;
|
|
4
|
+
export declare function trackedStructure<A>(c: Control<A>, tracker: ChangeListenerFunc<any>): A;
|
package/lib/util.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { CompoundField, ControlDefinition, DataControlDefinition, DisplayOnlyRenderOptions, FieldOption, GroupedControlsDefinition, SchemaField, SchemaInterface } from "./types";
|
|
2
2
|
import { MutableRefObject } from "react";
|
|
3
3
|
import { Control } from "@react-typed-forms/core";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
root: Control<any>;
|
|
4
|
+
import { DataContext, JsonPath } from "./controlRender";
|
|
5
|
+
export interface ControlDataContext extends DataContext {
|
|
7
6
|
fields: SchemaField[];
|
|
8
7
|
schemaInterface: SchemaInterface;
|
|
9
8
|
}
|
|
@@ -34,7 +33,9 @@ export declare function getDisplayOnlyOptions(d: ControlDefinition): DisplayOnly
|
|
|
34
33
|
export declare function getTypeField(context: ControlDataContext): Control<string> | undefined;
|
|
35
34
|
export declare function visitControlDataArray<A>(controls: ControlDefinition[] | undefined | null, context: ControlDataContext, cb: (definition: DataControlDefinition, field: SchemaField, control: Control<any>, element: boolean) => A | undefined): A | undefined;
|
|
36
35
|
export declare function visitControlData<A>(definition: ControlDefinition, ctx: ControlDataContext, cb: (definition: DataControlDefinition, field: SchemaField, control: Control<any>, element: boolean) => A | undefined): A | undefined;
|
|
36
|
+
export declare function lookupChildControl(data: DataContext, child: JsonPath): Control<any> | undefined;
|
|
37
37
|
export declare function cleanDataForSchema(v: {
|
|
38
38
|
[k: string]: any;
|
|
39
39
|
} | undefined, fields: SchemaField[]): any;
|
|
40
40
|
export declare function getAllReferencedClasses(c: ControlDefinition): string[];
|
|
41
|
+
export declare function jsonPathString(jsonPath: JsonPath[]): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-typed-forms/schemas",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"material-ui"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@react-typed-forms/core": "^3.
|
|
27
|
+
"@react-typed-forms/core": "^3.1.0",
|
|
28
28
|
"clsx": "^1 || ^2",
|
|
29
29
|
"jsonata": "^2.0.4",
|
|
30
30
|
"react": "^18.2.0"
|
package/src/controlRender.tsx
CHANGED
|
@@ -10,8 +10,10 @@ import React, {
|
|
|
10
10
|
import {
|
|
11
11
|
addElement,
|
|
12
12
|
Control,
|
|
13
|
+
ControlChange,
|
|
13
14
|
newControl,
|
|
14
15
|
removeElement,
|
|
16
|
+
trackControlChange,
|
|
15
17
|
useComponentTracking,
|
|
16
18
|
useControl,
|
|
17
19
|
useControlEffect,
|
|
@@ -166,6 +168,7 @@ export interface GroupRendererProps {
|
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
export interface DataRendererProps {
|
|
171
|
+
definition: DataControlDefinition;
|
|
169
172
|
renderOptions: RenderOptions;
|
|
170
173
|
field: SchemaField;
|
|
171
174
|
id: string;
|
|
@@ -192,6 +195,7 @@ export interface ActionRendererProps {
|
|
|
192
195
|
|
|
193
196
|
export interface ControlRenderProps {
|
|
194
197
|
control: Control<any>;
|
|
198
|
+
parentPath?: JsonPath[];
|
|
195
199
|
}
|
|
196
200
|
|
|
197
201
|
export interface FormContextOptions {
|
|
@@ -210,18 +214,23 @@ export interface DataControlProps {
|
|
|
210
214
|
childCount: number;
|
|
211
215
|
renderChild: ChildRenderer;
|
|
212
216
|
allowedOptions?: Control<any[] | undefined>;
|
|
213
|
-
elementRenderer?: (
|
|
217
|
+
elementRenderer?: (elemIndex: number) => ReactNode;
|
|
214
218
|
}
|
|
215
219
|
export type CreateDataProps = (
|
|
216
220
|
controlProps: DataControlProps,
|
|
217
221
|
) => DataRendererProps;
|
|
218
222
|
|
|
223
|
+
export type JsonPath = string | number;
|
|
224
|
+
|
|
225
|
+
export interface DataContext {
|
|
226
|
+
data: Control<any>;
|
|
227
|
+
path: JsonPath[];
|
|
228
|
+
}
|
|
219
229
|
export interface ControlRenderOptions extends FormContextOptions {
|
|
220
230
|
useDataHook?: (c: ControlDefinition) => CreateDataProps;
|
|
221
231
|
useEvalExpressionHook?: UseEvalExpressionHook;
|
|
222
232
|
clearHidden?: boolean;
|
|
223
233
|
schemaInterface?: SchemaInterface;
|
|
224
|
-
dataRoot?: Control<any>;
|
|
225
234
|
}
|
|
226
235
|
export function useControlRenderer(
|
|
227
236
|
definition: ControlDefinition,
|
|
@@ -258,22 +267,22 @@ export function useControlRenderer(
|
|
|
258
267
|
const r = useUpdatedRef({ options, definition, fields, schemaField });
|
|
259
268
|
|
|
260
269
|
const Component = useCallback(
|
|
261
|
-
({ control:
|
|
270
|
+
({ control: rootControl, parentPath = [] }: ControlRenderProps) => {
|
|
262
271
|
const stopTracking = useComponentTracking();
|
|
263
272
|
try {
|
|
264
273
|
const { definition: c, options, fields, schemaField } = r.current;
|
|
265
|
-
const
|
|
266
|
-
groupControl: parentControl,
|
|
274
|
+
const parentDataContext: ControlDataContext = {
|
|
267
275
|
fields,
|
|
268
276
|
schemaInterface,
|
|
269
|
-
|
|
277
|
+
data: rootControl,
|
|
278
|
+
path: parentPath,
|
|
270
279
|
};
|
|
271
|
-
const readonlyControl = useIsReadonly(
|
|
272
|
-
const disabledControl = useIsDisabled(
|
|
273
|
-
const visibleControl = useIsVisible(
|
|
274
|
-
const displayControl = useDynamicDisplay(
|
|
275
|
-
const customStyle = useCustomStyle(
|
|
276
|
-
const layoutStyle = useLayoutStyle(
|
|
280
|
+
const readonlyControl = useIsReadonly(parentDataContext);
|
|
281
|
+
const disabledControl = useIsDisabled(parentDataContext);
|
|
282
|
+
const visibleControl = useIsVisible(parentDataContext);
|
|
283
|
+
const displayControl = useDynamicDisplay(parentDataContext);
|
|
284
|
+
const customStyle = useCustomStyle(parentDataContext).value;
|
|
285
|
+
const layoutStyle = useLayoutStyle(parentDataContext).value;
|
|
277
286
|
const visible = visibleControl.current.value;
|
|
278
287
|
const visibility = useControl<Visibility | undefined>(() =>
|
|
279
288
|
visible != null
|
|
@@ -294,31 +303,33 @@ export function useControlRenderer(
|
|
|
294
303
|
},
|
|
295
304
|
);
|
|
296
305
|
|
|
297
|
-
const allowedOptions = useAllowedOptions(
|
|
298
|
-
const defaultValueControl = useDefaultValue(
|
|
299
|
-
const [control,
|
|
306
|
+
const allowedOptions = useAllowedOptions(parentDataContext);
|
|
307
|
+
const defaultValueControl = useDefaultValue(parentDataContext);
|
|
308
|
+
const [parentControl, control, controlDataContext] = getControlData(
|
|
300
309
|
schemaField,
|
|
301
|
-
|
|
310
|
+
parentDataContext,
|
|
302
311
|
);
|
|
303
312
|
useControlEffect(
|
|
304
313
|
() => [
|
|
305
314
|
visibility.value,
|
|
306
315
|
defaultValueControl.value,
|
|
307
316
|
control,
|
|
308
|
-
parentControl.isNull,
|
|
309
317
|
isDataControlDefinition(definition) && definition.dontClearHidden,
|
|
318
|
+
parentControl?.isNull,
|
|
310
319
|
],
|
|
311
|
-
([vc, dv, cd,
|
|
312
|
-
if (pn) {
|
|
313
|
-
parentControl.value = {};
|
|
314
|
-
}
|
|
320
|
+
([vc, dv, cd, dontClear, parentNull]) => {
|
|
315
321
|
if (vc && cd && vc.visible === vc.showing) {
|
|
316
322
|
if (!vc.visible) {
|
|
317
|
-
if (options.clearHidden && !dontClear)
|
|
323
|
+
if (options.clearHidden && !dontClear) {
|
|
324
|
+
cd.value = undefined;
|
|
325
|
+
}
|
|
318
326
|
} else if (cd.value == null) {
|
|
319
327
|
cd.value = dv;
|
|
320
328
|
}
|
|
321
329
|
}
|
|
330
|
+
if (parentNull && parentControl?.isNull) {
|
|
331
|
+
parentControl.value = {};
|
|
332
|
+
}
|
|
322
333
|
},
|
|
323
334
|
true,
|
|
324
335
|
);
|
|
@@ -327,20 +338,25 @@ export function useControlRenderer(
|
|
|
327
338
|
readonly: options.readonly || readonlyControl.value,
|
|
328
339
|
disabled: options.disabled || disabledControl.value,
|
|
329
340
|
})).value;
|
|
330
|
-
useValidation(
|
|
341
|
+
useValidation(
|
|
342
|
+
control ?? newControl(null),
|
|
343
|
+
!!myOptions.hidden,
|
|
344
|
+
parentDataContext,
|
|
345
|
+
);
|
|
331
346
|
const childRenderers: FC<ControlRenderProps>[] =
|
|
332
347
|
c.children?.map((cd) =>
|
|
333
|
-
useControlRenderer(cd,
|
|
348
|
+
useControlRenderer(cd, controlDataContext.fields, renderer, {
|
|
334
349
|
...options,
|
|
335
350
|
...myOptions,
|
|
336
|
-
dataRoot: dataContext.root,
|
|
337
351
|
}),
|
|
338
352
|
) ?? [];
|
|
353
|
+
|
|
339
354
|
useEffect(() => {
|
|
340
355
|
if (control && typeof myOptions.disabled === "boolean")
|
|
341
356
|
control.disabled = myOptions.disabled;
|
|
342
357
|
}, [control, myOptions.disabled]);
|
|
343
|
-
if (parentControl
|
|
358
|
+
if (parentControl?.isNull) return <></>;
|
|
359
|
+
|
|
344
360
|
const adornments =
|
|
345
361
|
definition.adornments?.map((x) =>
|
|
346
362
|
renderer.renderAdornment({ adornment: x }),
|
|
@@ -355,7 +371,7 @@ export function useControlRenderer(
|
|
|
355
371
|
},
|
|
356
372
|
createDataProps: dataProps,
|
|
357
373
|
formOptions: myOptions,
|
|
358
|
-
dataContext,
|
|
374
|
+
dataContext: controlDataContext,
|
|
359
375
|
control: displayControl ?? control,
|
|
360
376
|
schemaField,
|
|
361
377
|
displayControl,
|
|
@@ -406,17 +422,24 @@ export function lookupSchemaField(
|
|
|
406
422
|
export function getControlData(
|
|
407
423
|
schemaField: SchemaField | undefined,
|
|
408
424
|
parentContext: ControlDataContext,
|
|
409
|
-
): [Control<any> | undefined, ControlDataContext] {
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
425
|
+
): [Control<any> | undefined, Control<any> | undefined, ControlDataContext] {
|
|
426
|
+
const { data, path } = parentContext;
|
|
427
|
+
const parentControl = data.lookupControl(path);
|
|
428
|
+
const childPath = schemaField ? [...path, schemaField.field] : path;
|
|
429
|
+
const childControl =
|
|
430
|
+
schemaField && parentControl
|
|
431
|
+
? parentControl.fields[schemaField.field]
|
|
432
|
+
: undefined;
|
|
413
433
|
return [
|
|
434
|
+
parentControl,
|
|
414
435
|
childControl,
|
|
415
|
-
schemaField
|
|
436
|
+
schemaField
|
|
416
437
|
? {
|
|
417
438
|
...parentContext,
|
|
418
|
-
|
|
419
|
-
fields: schemaField
|
|
439
|
+
path: childPath,
|
|
440
|
+
fields: isCompoundField(schemaField)
|
|
441
|
+
? schemaField.children
|
|
442
|
+
: parentContext.fields,
|
|
420
443
|
}
|
|
421
444
|
: parentContext,
|
|
422
445
|
];
|
|
@@ -426,13 +449,14 @@ function groupProps(
|
|
|
426
449
|
renderOptions: GroupRenderOptions = { type: "Standard" },
|
|
427
450
|
childCount: number,
|
|
428
451
|
renderChild: ChildRenderer,
|
|
429
|
-
|
|
452
|
+
data: DataContext,
|
|
430
453
|
className: string | null | undefined,
|
|
431
454
|
style: React.CSSProperties | undefined,
|
|
432
455
|
): GroupRendererProps {
|
|
433
456
|
return {
|
|
434
457
|
childCount,
|
|
435
|
-
renderChild: (i) =>
|
|
458
|
+
renderChild: (i) =>
|
|
459
|
+
renderChild(i, i, { control: data.data, parentPath: data.path }),
|
|
436
460
|
renderOptions,
|
|
437
461
|
className: cc(className),
|
|
438
462
|
style,
|
|
@@ -455,6 +479,7 @@ export function defaultDataProps({
|
|
|
455
479
|
(field.options?.length ?? 0) === 0 ? null : field.options;
|
|
456
480
|
const allowed = allowedOptions?.value ?? [];
|
|
457
481
|
return {
|
|
482
|
+
definition,
|
|
458
483
|
control,
|
|
459
484
|
field,
|
|
460
485
|
id: "c" + control.uniqueId,
|
|
@@ -489,7 +514,7 @@ export function defaultArrayProps(
|
|
|
489
514
|
required: boolean,
|
|
490
515
|
style: CSSProperties | undefined,
|
|
491
516
|
className: string | undefined,
|
|
492
|
-
renderElement: (
|
|
517
|
+
renderElement: (elemIndex: number) => ReactNode,
|
|
493
518
|
): ArrayRendererProps {
|
|
494
519
|
const noun = field.displayName ?? field.field;
|
|
495
520
|
const elems = arrayControl.elements ?? [];
|
|
@@ -508,7 +533,7 @@ export function defaultArrayProps(
|
|
|
508
533
|
actionText: "Remove",
|
|
509
534
|
onClick: () => removeElement(arrayControl, i),
|
|
510
535
|
}),
|
|
511
|
-
renderElement: (i) => renderElement(
|
|
536
|
+
renderElement: (i) => renderElement(i),
|
|
512
537
|
className: cc(className),
|
|
513
538
|
style,
|
|
514
539
|
};
|
|
@@ -566,7 +591,7 @@ export function renderControlLayout({
|
|
|
566
591
|
c.groupOptions,
|
|
567
592
|
childCount,
|
|
568
593
|
childRenderer,
|
|
569
|
-
dataContext
|
|
594
|
+
dataContext,
|
|
570
595
|
c.styleClass,
|
|
571
596
|
style,
|
|
572
597
|
),
|
|
@@ -601,22 +626,26 @@ export function renderControlLayout({
|
|
|
601
626
|
}
|
|
602
627
|
return {};
|
|
603
628
|
|
|
604
|
-
function renderData(c: DataControlDefinition,
|
|
629
|
+
function renderData(c: DataControlDefinition, elemIndex?: number) {
|
|
605
630
|
if (!schemaField) return { children: "No schema field for: " + c.field };
|
|
631
|
+
if (!childControl) return { children: "No control for: " + c.field };
|
|
606
632
|
const props = dataProps({
|
|
607
633
|
definition: c,
|
|
608
634
|
field: schemaField,
|
|
609
|
-
dataContext
|
|
610
|
-
|
|
635
|
+
dataContext:
|
|
636
|
+
elemIndex != null
|
|
637
|
+
? { ...dataContext, path: [...dataContext.path, elemIndex] }
|
|
638
|
+
: dataContext,
|
|
639
|
+
control:
|
|
640
|
+
elemIndex != null ? childControl!.elements[elemIndex] : childControl,
|
|
611
641
|
options: dataOptions,
|
|
612
642
|
style,
|
|
613
643
|
childCount,
|
|
614
644
|
allowedOptions,
|
|
615
645
|
renderChild: childRenderer,
|
|
616
646
|
elementRenderer:
|
|
617
|
-
|
|
618
|
-
? (
|
|
619
|
-
renderLayoutParts(renderData(c, element), renderer).children
|
|
647
|
+
elemIndex == null && schemaField.collection
|
|
648
|
+
? (ei) => renderLayoutParts(renderData(c, ei), renderer).children
|
|
620
649
|
: undefined,
|
|
621
650
|
});
|
|
622
651
|
|
|
@@ -635,32 +664,6 @@ export function renderControlLayout({
|
|
|
635
664
|
errorControl: childControl,
|
|
636
665
|
};
|
|
637
666
|
}
|
|
638
|
-
|
|
639
|
-
function compoundRenderer(i: number, control: Control<any>): ReactNode {
|
|
640
|
-
const { className, style, children } = renderer.renderLayout({
|
|
641
|
-
processLayout: renderer.renderGroup({
|
|
642
|
-
renderOptions: { type: "Standard", hideTitle: true },
|
|
643
|
-
childCount,
|
|
644
|
-
renderChild: (ci) => childRenderer(ci, ci, { control }),
|
|
645
|
-
}),
|
|
646
|
-
});
|
|
647
|
-
return (
|
|
648
|
-
<div key={control.uniqueId} style={style} className={cc(className)}>
|
|
649
|
-
{children}
|
|
650
|
-
</div>
|
|
651
|
-
);
|
|
652
|
-
}
|
|
653
|
-
function scalarRenderer(
|
|
654
|
-
dataProps: DataRendererProps,
|
|
655
|
-
): (i: number, control: Control<any>) => ReactNode {
|
|
656
|
-
return (i, control) => {
|
|
657
|
-
return (
|
|
658
|
-
<Fragment key={control.uniqueId}>
|
|
659
|
-
{renderer.renderData({ ...dataProps, control })({}).children}
|
|
660
|
-
</Fragment>
|
|
661
|
-
);
|
|
662
|
-
};
|
|
663
|
-
}
|
|
664
667
|
}
|
|
665
668
|
|
|
666
669
|
export function appendMarkup(
|
|
@@ -740,3 +743,23 @@ export function controlTitle(
|
|
|
740
743
|
) {
|
|
741
744
|
return title ? title : fieldDisplayName(field);
|
|
742
745
|
}
|
|
746
|
+
|
|
747
|
+
function lookupControl(
|
|
748
|
+
base: Control<any> | undefined,
|
|
749
|
+
path: (string | number)[],
|
|
750
|
+
): Control<any> | undefined {
|
|
751
|
+
let index = 0;
|
|
752
|
+
while (index < path.length && base) {
|
|
753
|
+
const childId = path[index];
|
|
754
|
+
const c = base.current;
|
|
755
|
+
if (typeof childId === "string") {
|
|
756
|
+
const next = c.fields?.[childId];
|
|
757
|
+
if (!next) trackControlChange(base, ControlChange.Structure);
|
|
758
|
+
base = next;
|
|
759
|
+
} else {
|
|
760
|
+
base = c.elements?.[childId];
|
|
761
|
+
}
|
|
762
|
+
index++;
|
|
763
|
+
}
|
|
764
|
+
return base;
|
|
765
|
+
}
|
package/src/hooks.tsx
CHANGED
|
@@ -10,12 +10,15 @@ import {
|
|
|
10
10
|
SchemaField,
|
|
11
11
|
SchemaInterface,
|
|
12
12
|
} from "./types";
|
|
13
|
-
import { useCallback, useMemo } from "react";
|
|
13
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
14
14
|
import {
|
|
15
|
+
addAfterChangesCallback,
|
|
16
|
+
collectChanges,
|
|
15
17
|
Control,
|
|
18
|
+
makeChangeTracker,
|
|
16
19
|
useComputed,
|
|
17
20
|
useControl,
|
|
18
|
-
|
|
21
|
+
useRefState,
|
|
19
22
|
} from "@react-typed-forms/core";
|
|
20
23
|
|
|
21
24
|
import {
|
|
@@ -25,10 +28,13 @@ import {
|
|
|
25
28
|
getDisplayOnlyOptions,
|
|
26
29
|
getTypeField,
|
|
27
30
|
isControlReadonly,
|
|
31
|
+
jsonPathString,
|
|
32
|
+
lookupChildControl,
|
|
28
33
|
useUpdatedRef,
|
|
29
34
|
} from "./util";
|
|
30
35
|
import jsonata from "jsonata";
|
|
31
|
-
import { useCalculatedControl } from "./internal";
|
|
36
|
+
import { trackedStructure, useCalculatedControl } from "./internal";
|
|
37
|
+
import { DataContext } from "./controlRender";
|
|
32
38
|
|
|
33
39
|
export type UseEvalExpressionHook = (
|
|
34
40
|
expr: EntityExpression | undefined,
|
|
@@ -192,20 +198,24 @@ export type EvalExpressionHook<A = any> = (
|
|
|
192
198
|
function useDataExpression(
|
|
193
199
|
fvExpr: DataExpression,
|
|
194
200
|
fields: SchemaField[],
|
|
195
|
-
data:
|
|
201
|
+
data: DataContext,
|
|
196
202
|
) {
|
|
197
203
|
const refField = findField(fields, fvExpr.field);
|
|
198
|
-
const otherField = refField
|
|
204
|
+
const otherField = refField
|
|
205
|
+
? lookupChildControl(data, refField.field)
|
|
206
|
+
: undefined;
|
|
199
207
|
return useCalculatedControl(() => otherField?.value);
|
|
200
208
|
}
|
|
201
209
|
|
|
202
210
|
function useDataMatchExpression(
|
|
203
211
|
fvExpr: DataMatchExpression,
|
|
204
212
|
fields: SchemaField[],
|
|
205
|
-
data:
|
|
213
|
+
data: DataContext,
|
|
206
214
|
) {
|
|
207
215
|
const refField = findField(fields, fvExpr.field);
|
|
208
|
-
const otherField = refField
|
|
216
|
+
const otherField = refField
|
|
217
|
+
? lookupChildControl(data, refField.field)
|
|
218
|
+
: undefined;
|
|
209
219
|
return useComputed(() => {
|
|
210
220
|
const fv = otherField?.value;
|
|
211
221
|
return Array.isArray(fv) ? fv.includes(fvExpr.value) : fv === fvExpr.value;
|
|
@@ -220,20 +230,15 @@ export function defaultEvalHooks(
|
|
|
220
230
|
case ExpressionType.Jsonata:
|
|
221
231
|
return useJsonataExpression(
|
|
222
232
|
(expr as JsonataExpression).expression,
|
|
223
|
-
context
|
|
224
|
-
context.root,
|
|
233
|
+
context,
|
|
225
234
|
);
|
|
226
235
|
case ExpressionType.Data:
|
|
227
|
-
return useDataExpression(
|
|
228
|
-
expr as DataExpression,
|
|
229
|
-
context.fields,
|
|
230
|
-
context.groupControl,
|
|
231
|
-
);
|
|
236
|
+
return useDataExpression(expr as DataExpression, context.fields, context);
|
|
232
237
|
case ExpressionType.DataMatch:
|
|
233
238
|
return useDataMatchExpression(
|
|
234
239
|
expr as DataMatchExpression,
|
|
235
240
|
context.fields,
|
|
236
|
-
context
|
|
241
|
+
context,
|
|
237
242
|
);
|
|
238
243
|
default:
|
|
239
244
|
return useControl(undefined);
|
|
@@ -291,31 +296,57 @@ export function hideDisplayOnly(
|
|
|
291
296
|
!displayOptions.emptyText &&
|
|
292
297
|
schemaInterface.isEmptyValue(
|
|
293
298
|
field,
|
|
294
|
-
context
|
|
299
|
+
lookupChildControl(context, field.field)?.value,
|
|
295
300
|
)
|
|
296
301
|
);
|
|
297
302
|
}
|
|
298
303
|
|
|
299
304
|
export function useJsonataExpression(
|
|
300
305
|
jExpr: string,
|
|
301
|
-
|
|
302
|
-
|
|
306
|
+
dataContext: DataContext,
|
|
307
|
+
bindings?: () => Record<string, any>,
|
|
303
308
|
): Control<any> {
|
|
309
|
+
const pathString = jsonPathString(dataContext.path);
|
|
304
310
|
const compiledExpr = useMemo(() => {
|
|
305
311
|
try {
|
|
306
|
-
return jsonata(jExpr);
|
|
312
|
+
return jsonata(pathString ? pathString + ".(" + jExpr + ")" : jExpr);
|
|
307
313
|
} catch (e) {
|
|
308
314
|
console.error(e);
|
|
309
315
|
return jsonata("null");
|
|
310
316
|
}
|
|
311
|
-
}, [jExpr]);
|
|
317
|
+
}, [jExpr, pathString]);
|
|
312
318
|
const control = useControl();
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
+
const listenerRef = useRef<() => void>();
|
|
320
|
+
const [ref] = useRefState(() =>
|
|
321
|
+
makeChangeTracker(() => {
|
|
322
|
+
const l = listenerRef.current;
|
|
323
|
+
if (l) {
|
|
324
|
+
listenerRef.current = undefined;
|
|
325
|
+
addAfterChangesCallback(() => {
|
|
326
|
+
l();
|
|
327
|
+
listenerRef.current = l;
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}),
|
|
319
331
|
);
|
|
332
|
+
useEffect(() => {
|
|
333
|
+
listenerRef.current = apply;
|
|
334
|
+
apply();
|
|
335
|
+
async function apply() {
|
|
336
|
+
const [collect, updateSubscriptions] = ref.current;
|
|
337
|
+
try {
|
|
338
|
+
const bindingData = bindings
|
|
339
|
+
? collectChanges(collect, bindings)
|
|
340
|
+
: undefined;
|
|
341
|
+
control.value = await compiledExpr.evaluate(
|
|
342
|
+
trackedStructure(dataContext.data, collect),
|
|
343
|
+
bindingData,
|
|
344
|
+
);
|
|
345
|
+
} finally {
|
|
346
|
+
updateSubscriptions();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return () => ref.current[1](true);
|
|
350
|
+
}, [compiledExpr]);
|
|
320
351
|
return control;
|
|
321
352
|
}
|
package/src/internal.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ChangeListenerFunc,
|
|
3
|
+
Control,
|
|
4
|
+
ControlChange,
|
|
5
|
+
useControl,
|
|
6
|
+
useControlEffect,
|
|
7
|
+
} from "@react-typed-forms/core";
|
|
2
8
|
|
|
3
9
|
export function useCalculatedControl<V>(calculate: () => V): Control<V> {
|
|
4
10
|
const c = useControl(calculate);
|
|
@@ -9,3 +15,34 @@ export function useCalculatedControl<V>(calculate: () => V): Control<V> {
|
|
|
9
15
|
export function cc(n: string | null | undefined): string | undefined {
|
|
10
16
|
return n ? n : undefined;
|
|
11
17
|
}
|
|
18
|
+
|
|
19
|
+
export function trackedStructure<A>(
|
|
20
|
+
c: Control<A>,
|
|
21
|
+
tracker: ChangeListenerFunc<any>,
|
|
22
|
+
): A {
|
|
23
|
+
const cc = c.current;
|
|
24
|
+
const cv = cc.value;
|
|
25
|
+
if (cv == null) {
|
|
26
|
+
tracker(c, ControlChange.Structure);
|
|
27
|
+
return cv;
|
|
28
|
+
}
|
|
29
|
+
if (typeof cv !== "object") {
|
|
30
|
+
tracker(c, ControlChange.Value);
|
|
31
|
+
return cv;
|
|
32
|
+
}
|
|
33
|
+
return new Proxy(cv, {
|
|
34
|
+
get(target: object, p: string | symbol, receiver: any): any {
|
|
35
|
+
if (Array.isArray(cv)) {
|
|
36
|
+
tracker(c, ControlChange.Structure);
|
|
37
|
+
if (typeof p === "symbol" || p[0] >= "9" || p[0] < "0")
|
|
38
|
+
return Reflect.get(cv, p);
|
|
39
|
+
const nc = (cc.elements as any)[p];
|
|
40
|
+
if (typeof nc === "function") return nc;
|
|
41
|
+
if (nc == null) return null;
|
|
42
|
+
return trackedStructure(nc, tracker);
|
|
43
|
+
}
|
|
44
|
+
if (p in cv) return trackedStructure((cc.fields as any)[p], tracker);
|
|
45
|
+
return undefined;
|
|
46
|
+
},
|
|
47
|
+
}) as A;
|
|
48
|
+
}
|
package/src/renderers.tsx
CHANGED
|
@@ -428,8 +428,8 @@ export function createDefaultGroupRenderer(
|
|
|
428
428
|
const { style, className: gcn } = isGridRenderer(renderOptions)
|
|
429
429
|
? gridStyles(renderOptions)
|
|
430
430
|
: isFlexRenderer(renderOptions)
|
|
431
|
-
|
|
432
|
-
|
|
431
|
+
? flexStyles(renderOptions)
|
|
432
|
+
: ({ className: standardClassName } as StyleProps);
|
|
433
433
|
|
|
434
434
|
return (cp: ControlLayoutProps) => {
|
|
435
435
|
return {
|
|
@@ -531,7 +531,11 @@ export function createDefaultDataRenderer(
|
|
|
531
531
|
style: props.style,
|
|
532
532
|
className: props.className,
|
|
533
533
|
renderOptions: { type: "Standard", hideTitle: true },
|
|
534
|
-
renderChild: (i) =>
|
|
534
|
+
renderChild: (i) =>
|
|
535
|
+
props.renderChild(i, i, {
|
|
536
|
+
control: props.dataContext.data,
|
|
537
|
+
parentPath: props.dataContext.path,
|
|
538
|
+
}),
|
|
535
539
|
childCount: props.childCount,
|
|
536
540
|
});
|
|
537
541
|
}
|