@react-typed-forms/schemas 15.2.0 → 16.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/RenderForm.d.ts +39 -0
- package/lib/controlBuilder.d.ts +3 -6
- package/lib/controlRender.d.ts +107 -87
- package/lib/index.cjs +535 -2117
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.ts +3 -9
- package/lib/index.js +402 -1639
- package/lib/index.js.map +1 -1
- package/lib/renderers.d.ts +3 -3
- package/lib/types.d.ts +31 -0
- package/lib/util.d.ts +8 -54
- package/package.json +5 -4
- package/src/RenderForm.tsx +301 -0
- package/src/controlBuilder.ts +22 -19
- package/src/controlRender.tsx +228 -507
- package/src/createFormRenderer.tsx +4 -5
- package/src/index.ts +3 -9
- package/src/renderers.tsx +2 -3
- package/src/types.ts +52 -0
- package/src/util.ts +149 -183
- package/lib/controlDefinition.d.ts +0 -398
- package/lib/defaultSchemaInterface.d.ts +0 -24
- package/lib/dynamicHooks.d.ts +0 -54
- package/lib/entityExpression.d.ts +0 -32
- package/lib/hooks.d.ts +0 -28
- package/lib/schemaBuilder.d.ts +0 -67
- package/lib/schemaField.d.ts +0 -252
- package/lib/schemaValidator.d.ts +0 -27
- package/lib/validators.d.ts +0 -19
- package/src/controlDefinition.ts +0 -821
- package/src/defaultSchemaInterface.ts +0 -191
- package/src/dynamicHooks.ts +0 -98
- package/src/entityExpression.ts +0 -38
- package/src/hooks.tsx +0 -469
- package/src/schemaBuilder.ts +0 -318
- package/src/schemaField.ts +0 -552
- package/src/schemaValidator.ts +0 -32
- package/src/validators.ts +0 -217
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
2
|
import {
|
|
3
|
-
ActionRendererProps,
|
|
4
3
|
AdornmentProps,
|
|
5
4
|
AdornmentRenderer,
|
|
6
5
|
ArrayRendererProps,
|
|
@@ -27,7 +26,8 @@ import {
|
|
|
27
26
|
RendererRegistration,
|
|
28
27
|
VisibilityRendererRegistration,
|
|
29
28
|
} from "./renderers";
|
|
30
|
-
import { DataRenderType } from "
|
|
29
|
+
import { DataRenderType } from "@astroapps/forms-core";
|
|
30
|
+
import { ActionRendererProps } from "./types";
|
|
31
31
|
|
|
32
32
|
export function createFormRenderer(
|
|
33
33
|
customRenderers: RendererRegistration[] = [],
|
|
@@ -59,7 +59,6 @@ export function createFormRenderer(
|
|
|
59
59
|
renderLayout,
|
|
60
60
|
renderVisibility,
|
|
61
61
|
renderLabelText,
|
|
62
|
-
renderText: defaultRenderers.renderText,
|
|
63
62
|
html: defaultRenderers.html,
|
|
64
63
|
};
|
|
65
64
|
|
|
@@ -125,7 +124,7 @@ export function createFormRenderer(
|
|
|
125
124
|
if (noMatch === true) return false;
|
|
126
125
|
const matchCollection =
|
|
127
126
|
(x.collection ?? false) ===
|
|
128
|
-
(props.elementIndex == null && (field.collection ?? false));
|
|
127
|
+
(props.dataNode.elementIndex == null && (field.collection ?? false));
|
|
129
128
|
const isSchemaAllowed =
|
|
130
129
|
!!x.schemaType && renderType == DataRenderType.Standard
|
|
131
130
|
? isOneOf(x.schemaType, field.type)
|
package/src/index.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
export * from "
|
|
2
|
-
export * from "./schemaBuilder";
|
|
1
|
+
export * from "@astroapps/forms-core";
|
|
3
2
|
export * from "./controlBuilder";
|
|
4
3
|
export * from "./controlRender";
|
|
5
4
|
export * from "./util";
|
|
6
5
|
export * from "./renderers";
|
|
7
|
-
export * from "./validators";
|
|
8
|
-
export * from "./hooks";
|
|
9
|
-
export * from "./defaultSchemaInterface";
|
|
10
6
|
export * from "./createFormRenderer";
|
|
11
|
-
export * from "./
|
|
12
|
-
export * from "./
|
|
13
|
-
export * from "./schemaField";
|
|
14
|
-
export * from "./entityExpression";
|
|
7
|
+
export * from "./RenderForm";
|
|
8
|
+
export * from "./types";
|
package/src/renderers.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ReactElement, ReactNode } from "react";
|
|
2
2
|
import {
|
|
3
|
-
ActionRendererProps,
|
|
4
3
|
AdornmentProps,
|
|
5
4
|
AdornmentRenderer,
|
|
6
5
|
ArrayRendererProps,
|
|
@@ -23,7 +22,8 @@ import {
|
|
|
23
22
|
OptionalAdornment,
|
|
24
23
|
RenderOptions,
|
|
25
24
|
SetFieldAdornment,
|
|
26
|
-
} from "
|
|
25
|
+
} from "@astroapps/forms-core";
|
|
26
|
+
import { ActionRendererProps } from "./types";
|
|
27
27
|
|
|
28
28
|
export interface DefaultRenderers {
|
|
29
29
|
data: DataRendererRegistration;
|
|
@@ -36,7 +36,6 @@ export interface DefaultRenderers {
|
|
|
36
36
|
renderLayout: LayoutRendererRegistration;
|
|
37
37
|
visibility: VisibilityRendererRegistration;
|
|
38
38
|
extraRenderers: RendererRegistration[];
|
|
39
|
-
renderText: (props: ReactNode) => ReactNode;
|
|
40
39
|
html: HtmlComponents;
|
|
41
40
|
}
|
|
42
41
|
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ActionStyle,
|
|
3
|
+
EntityExpression,
|
|
4
|
+
FormContextData,
|
|
5
|
+
IconPlacement,
|
|
6
|
+
IconReference,
|
|
7
|
+
SchemaDataNode,
|
|
8
|
+
SchemaInterface,
|
|
9
|
+
} from "@astroapps/forms-core";
|
|
10
|
+
import React, { Key, ReactNode } from "react";
|
|
11
|
+
import { CleanupScope } from "@react-typed-forms/core";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Interface representing the control data context.
|
|
15
|
+
*/
|
|
16
|
+
export interface ControlDataContext {
|
|
17
|
+
schemaInterface: SchemaInterface;
|
|
18
|
+
dataNode: SchemaDataNode | undefined;
|
|
19
|
+
parentNode: SchemaDataNode;
|
|
20
|
+
variables: Record<string, any>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type ControlActionHandler = (
|
|
24
|
+
actionId: string,
|
|
25
|
+
actionData: any,
|
|
26
|
+
ctx: ControlDataContext,
|
|
27
|
+
) => (() => void) | undefined;
|
|
28
|
+
|
|
29
|
+
export interface ActionRendererProps {
|
|
30
|
+
key?: Key;
|
|
31
|
+
actionId: string;
|
|
32
|
+
actionContent?: ReactNode;
|
|
33
|
+
actionText: string;
|
|
34
|
+
actionData?: any;
|
|
35
|
+
actionStyle?: ActionStyle | null;
|
|
36
|
+
icon?: IconReference | null;
|
|
37
|
+
iconPlacement?: IconPlacement | null;
|
|
38
|
+
onClick: () => void;
|
|
39
|
+
className?: string | null;
|
|
40
|
+
textClass?: string | null;
|
|
41
|
+
style?: React.CSSProperties;
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
hidden?: boolean;
|
|
44
|
+
inline?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type RunExpression = (
|
|
48
|
+
scope: CleanupScope,
|
|
49
|
+
expression: EntityExpression,
|
|
50
|
+
returnResult: (v: unknown) => void,
|
|
51
|
+
bindings?: FormContextData,
|
|
52
|
+
) => void;
|
package/src/util.ts
CHANGED
|
@@ -1,49 +1,54 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
CompoundField,
|
|
3
3
|
ControlDataVisitor,
|
|
4
4
|
ControlDefinition,
|
|
5
5
|
ControlDefinitionType,
|
|
6
|
-
|
|
6
|
+
createSchemaTree,
|
|
7
7
|
DataControlDefinition,
|
|
8
8
|
DataRenderType,
|
|
9
9
|
DisplayOnlyRenderOptions,
|
|
10
|
+
EntityExpression,
|
|
11
|
+
FieldOption,
|
|
10
12
|
fieldPathForDefinition,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
findField,
|
|
14
|
+
FormContextData,
|
|
15
|
+
getGroupRendererOptions,
|
|
16
|
+
getTagParam,
|
|
13
17
|
GroupRenderOptions,
|
|
14
18
|
isAutoCompleteClasses,
|
|
15
19
|
isCheckEntryClasses,
|
|
20
|
+
isCompoundField,
|
|
21
|
+
isCompoundNode,
|
|
16
22
|
isDataControl,
|
|
17
23
|
isDataGroupRenderer,
|
|
18
24
|
isDisplayOnlyRenderer,
|
|
25
|
+
isGridRenderer,
|
|
19
26
|
isGroupControl,
|
|
20
|
-
} from "./controlDefinition";
|
|
21
|
-
import { MutableRefObject, useRef } from "react";
|
|
22
|
-
import clsx from "clsx";
|
|
23
|
-
import {
|
|
24
|
-
CompoundField,
|
|
25
|
-
FieldOption,
|
|
26
|
-
findField,
|
|
27
|
-
getTagParam,
|
|
28
|
-
isCompoundField,
|
|
29
|
-
isCompoundNode,
|
|
30
27
|
isScalarField,
|
|
31
28
|
relativePath,
|
|
32
|
-
rootSchemaNode,
|
|
33
29
|
SchemaDataNode,
|
|
34
30
|
SchemaField,
|
|
35
31
|
schemaForFieldPath,
|
|
36
32
|
SchemaNode,
|
|
37
33
|
SchemaTags,
|
|
38
|
-
} from "
|
|
34
|
+
} from "@astroapps/forms-core";
|
|
35
|
+
import { MutableRefObject, useRef } from "react";
|
|
36
|
+
import clsx from "clsx";
|
|
39
37
|
import {
|
|
40
38
|
Control,
|
|
41
39
|
ControlChange,
|
|
40
|
+
createScopedEffect,
|
|
42
41
|
ensureMetaValue,
|
|
43
42
|
getElementIndex,
|
|
44
43
|
newControl,
|
|
44
|
+
useControl,
|
|
45
45
|
} from "@react-typed-forms/core";
|
|
46
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
ActionRendererProps,
|
|
48
|
+
ControlActionHandler,
|
|
49
|
+
RunExpression,
|
|
50
|
+
} from "./types";
|
|
51
|
+
import { Expression } from "jsonata";
|
|
47
52
|
|
|
48
53
|
/**
|
|
49
54
|
* Interface representing the classes for a control.
|
|
@@ -52,13 +57,10 @@ export interface ControlClasses {
|
|
|
52
57
|
styleClass?: string;
|
|
53
58
|
layoutClass?: string;
|
|
54
59
|
labelClass?: string;
|
|
60
|
+
textClass?: string;
|
|
61
|
+
labelTextClass?: string;
|
|
55
62
|
}
|
|
56
63
|
|
|
57
|
-
/**
|
|
58
|
-
* Type representing a JSON path, which can be a string or a number.
|
|
59
|
-
*/
|
|
60
|
-
export type JsonPath = string | number;
|
|
61
|
-
|
|
62
64
|
/**
|
|
63
65
|
* Applies default values to the given record based on the provided schema fields.
|
|
64
66
|
* @param v - The record to apply default values to.
|
|
@@ -146,7 +148,7 @@ export function defaultValueForField(
|
|
|
146
148
|
const isRequired = !!(required || sf.required);
|
|
147
149
|
if (isCompoundField(sf)) {
|
|
148
150
|
if (isRequired) {
|
|
149
|
-
const childValue = defaultValueForFields(sf.children);
|
|
151
|
+
const childValue = defaultValueForFields(sf.children ?? []);
|
|
150
152
|
return sf.collection ? [childValue] : childValue;
|
|
151
153
|
}
|
|
152
154
|
return sf.notNullable ? (sf.collection ? [] : {}) : undefined;
|
|
@@ -164,7 +166,7 @@ export function defaultValueForField(
|
|
|
164
166
|
*/
|
|
165
167
|
export function elementValueForField(sf: SchemaField): any {
|
|
166
168
|
if (isCompoundField(sf)) {
|
|
167
|
-
return defaultValueForFields(sf.children);
|
|
169
|
+
return defaultValueForFields(sf.children ?? []);
|
|
168
170
|
}
|
|
169
171
|
return sf.defaultValue;
|
|
170
172
|
}
|
|
@@ -344,31 +346,18 @@ export function addMissingControls(
|
|
|
344
346
|
controls: ControlDefinition[],
|
|
345
347
|
warning?: (msg: string) => void,
|
|
346
348
|
) {
|
|
347
|
-
return addMissingControlsForSchema(
|
|
349
|
+
return addMissingControlsForSchema(
|
|
350
|
+
createSchemaTree(fields).rootNode,
|
|
351
|
+
controls,
|
|
352
|
+
warning,
|
|
353
|
+
);
|
|
348
354
|
}
|
|
349
355
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
const controlPath = fieldPathForDefinition(c);
|
|
356
|
-
let dataSchema = controlPath
|
|
357
|
-
? schemaForFieldPath(controlPath, parentSchema)
|
|
358
|
-
: undefined;
|
|
359
|
-
if (isGroupControl(c) && dataSchema == null) dataSchema = parentSchema;
|
|
360
|
-
if (dataSchema) {
|
|
361
|
-
formToSchema[node.id] = dataSchema;
|
|
362
|
-
const formNodes = schemaToForm[dataSchema.id] ?? [];
|
|
363
|
-
formNodes.push(node);
|
|
364
|
-
schemaToForm[dataSchema.id] = formNodes;
|
|
365
|
-
}
|
|
366
|
-
node
|
|
367
|
-
.getChildNodes()
|
|
368
|
-
.forEach((x) => register(x, dataSchema ?? parentSchema));
|
|
369
|
-
}
|
|
370
|
-
register(formNode, parentSchema);
|
|
371
|
-
return { formToSchema, schemaToForm, register };
|
|
356
|
+
interface ControlAndSchema {
|
|
357
|
+
control: ControlDefinition;
|
|
358
|
+
children: ControlAndSchema[];
|
|
359
|
+
schema?: SchemaNode;
|
|
360
|
+
parent?: ControlAndSchema;
|
|
372
361
|
}
|
|
373
362
|
|
|
374
363
|
/**
|
|
@@ -382,77 +371,56 @@ export function addMissingControlsForSchema(
|
|
|
382
371
|
schema: SchemaNode,
|
|
383
372
|
controls: ControlDefinition[],
|
|
384
373
|
warning?: (msg: string) => void,
|
|
385
|
-
) {
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
374
|
+
): ControlDefinition[] {
|
|
375
|
+
const controlMap: { [k: string]: ControlAndSchema } = {};
|
|
376
|
+
const schemaControlMap: { [k: string]: ControlAndSchema[] } = {};
|
|
377
|
+
const rootControls = controls.map((c) => toControlAndSchema(c, schema));
|
|
378
|
+
const rootSchema = { schema, children: rootControls } as ControlAndSchema;
|
|
379
|
+
addSchemaMapEntry("", rootSchema);
|
|
380
|
+
rootControls.forEach(addReferences);
|
|
381
|
+
const fields = schema.getChildNodes();
|
|
382
|
+
fields.forEach(addMissing);
|
|
383
|
+
return rootControls.map(toDefinition);
|
|
384
|
+
|
|
385
|
+
function toDefinition(c: ControlAndSchema): ControlDefinition {
|
|
386
|
+
const children = c.children.length ? c.children.map(toDefinition) : null;
|
|
387
|
+
return { ...c.control, children };
|
|
395
388
|
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Adds missing controls to the provided form tree based on the schema fields.
|
|
400
|
-
* @param schema - The root schema node to use for adding missing controls.
|
|
401
|
-
* @param tree - The form tree to add missing controls to.
|
|
402
|
-
* @param warning - An optional function to call with warning messages.
|
|
403
|
-
*/
|
|
404
|
-
export function addMissingControlsToForm(
|
|
405
|
-
schema: SchemaNode,
|
|
406
|
-
tree: FormTree,
|
|
407
|
-
warning?: (msg: string) => void,
|
|
408
|
-
): void {
|
|
409
|
-
const { formToSchema, schemaToForm, register } = registerSchemaEntries(
|
|
410
|
-
tree.rootNode,
|
|
411
|
-
schema,
|
|
412
|
-
);
|
|
413
|
-
|
|
414
|
-
schema.getChildNodes().forEach(addMissing);
|
|
415
|
-
return;
|
|
416
389
|
|
|
417
390
|
function addMissing(schemaNode: SchemaNode) {
|
|
418
391
|
if (fieldHasTag(schemaNode.field, SchemaTags.NoControl)) return;
|
|
419
392
|
let skipChildren = false;
|
|
420
|
-
const existingControls =
|
|
393
|
+
const existingControls = schemaControlMap[schemaNode.id];
|
|
421
394
|
if (!existingControls) {
|
|
422
395
|
const eligibleParents = getEligibleParents(schemaNode);
|
|
423
396
|
const desiredGroup = getTagParam(
|
|
424
397
|
schemaNode.field,
|
|
425
398
|
SchemaTags.ControlGroup,
|
|
426
399
|
);
|
|
427
|
-
let parentGroup = desiredGroup
|
|
428
|
-
? tree.getByRefId(desiredGroup)
|
|
429
|
-
: undefined;
|
|
400
|
+
let parentGroup = desiredGroup ? controlMap[desiredGroup] : undefined;
|
|
430
401
|
if (!parentGroup && desiredGroup)
|
|
431
402
|
warning?.("No group '" + desiredGroup + "' for " + schemaNode.id);
|
|
432
|
-
if (
|
|
433
|
-
parentGroup &&
|
|
434
|
-
eligibleParents.indexOf(formToSchema[parentGroup.id]!.id) < 0
|
|
435
|
-
) {
|
|
403
|
+
if (parentGroup && eligibleParents.indexOf(parentGroup.schema!.id) < 0) {
|
|
436
404
|
warning?.(
|
|
437
405
|
`Target group '${desiredGroup}' is not an eligible parent for '${schemaNode.id}'`,
|
|
438
406
|
);
|
|
439
407
|
parentGroup = undefined;
|
|
440
408
|
}
|
|
441
409
|
if (!parentGroup && eligibleParents.length) {
|
|
442
|
-
parentGroup =
|
|
410
|
+
parentGroup = schemaControlMap[eligibleParents[0]]?.[0];
|
|
443
411
|
}
|
|
444
412
|
if (parentGroup) {
|
|
445
413
|
const newControl = defaultControlForField(schemaNode.field, true);
|
|
446
414
|
skipChildren = !!newControl.childRefId;
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
415
|
+
newControl.field = relativePath(parentGroup.schema!, schemaNode);
|
|
416
|
+
parentGroup.children.push(
|
|
417
|
+
toControlAndSchema(newControl, parentGroup.schema!, parentGroup),
|
|
418
|
+
);
|
|
451
419
|
} else warning?.("Could not find a parent group for: " + schemaNode.id);
|
|
452
420
|
} else {
|
|
453
|
-
skipChildren = existingControls.some((x) => x.
|
|
421
|
+
skipChildren = existingControls.some((x) => x.control.childRefId);
|
|
454
422
|
}
|
|
455
|
-
if (!skipChildren) schemaNode.getChildNodes(
|
|
423
|
+
if (!skipChildren) schemaNode.getChildNodes().forEach(addMissing);
|
|
456
424
|
}
|
|
457
425
|
|
|
458
426
|
function getEligibleParents(schemaNode: SchemaNode) {
|
|
@@ -461,7 +429,7 @@ export function addMissingControlsToForm(
|
|
|
461
429
|
while (parent) {
|
|
462
430
|
eligibleParents.push(parent.id);
|
|
463
431
|
if (parent.field.collection) break;
|
|
464
|
-
if (!parent.parent) parent.getChildNodes(
|
|
432
|
+
if (!parent.parent) parent.getChildNodes().forEach(addCompound);
|
|
465
433
|
parent = parent.parent;
|
|
466
434
|
}
|
|
467
435
|
return eligibleParents;
|
|
@@ -469,10 +437,56 @@ export function addMissingControlsToForm(
|
|
|
469
437
|
function addCompound(node: SchemaNode) {
|
|
470
438
|
if (isCompoundNode(node) && !node.field.collection) {
|
|
471
439
|
eligibleParents.push(node.id);
|
|
472
|
-
node.getChildNodes(
|
|
440
|
+
node.getChildNodes().forEach(addCompound);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function addReferences(c: ControlAndSchema) {
|
|
446
|
+
c.children.forEach(addReferences);
|
|
447
|
+
if (c.control.childRefId) {
|
|
448
|
+
const ref = controlMap[c.control.childRefId];
|
|
449
|
+
if (ref) {
|
|
450
|
+
ref.children.forEach((x) =>
|
|
451
|
+
toControlAndSchema(x.control, c.schema!, c, true),
|
|
452
|
+
);
|
|
453
|
+
return;
|
|
473
454
|
}
|
|
455
|
+
console.warn("Missing reference", c.control.childRefId);
|
|
474
456
|
}
|
|
475
457
|
}
|
|
458
|
+
|
|
459
|
+
function addSchemaMapEntry(schemaId: string, entry: ControlAndSchema) {
|
|
460
|
+
if (!schemaControlMap[schemaId]) schemaControlMap[schemaId] = [];
|
|
461
|
+
schemaControlMap[schemaId].push(entry);
|
|
462
|
+
}
|
|
463
|
+
function toControlAndSchema(
|
|
464
|
+
c: ControlDefinition,
|
|
465
|
+
parentSchema: SchemaNode,
|
|
466
|
+
parentNode?: ControlAndSchema,
|
|
467
|
+
dontRegister?: boolean,
|
|
468
|
+
): ControlAndSchema {
|
|
469
|
+
const controlPath = fieldPathForDefinition(c);
|
|
470
|
+
let dataSchema = controlPath
|
|
471
|
+
? schemaForFieldPath(controlPath, parentSchema)
|
|
472
|
+
: undefined;
|
|
473
|
+
if (isGroupControl(c) && dataSchema == null) dataSchema = parentSchema;
|
|
474
|
+
const entry: ControlAndSchema = {
|
|
475
|
+
schema: dataSchema,
|
|
476
|
+
control: c,
|
|
477
|
+
children: [],
|
|
478
|
+
parent: parentNode,
|
|
479
|
+
};
|
|
480
|
+
entry.children =
|
|
481
|
+
c.children?.map((x) =>
|
|
482
|
+
toControlAndSchema(x, dataSchema ?? parentSchema, entry, dontRegister),
|
|
483
|
+
) ?? [];
|
|
484
|
+
if (!dontRegister && c.id) controlMap[c.id] = entry;
|
|
485
|
+
if (dataSchema) {
|
|
486
|
+
addSchemaMapEntry(dataSchema.id, entry);
|
|
487
|
+
}
|
|
488
|
+
return entry;
|
|
489
|
+
}
|
|
476
490
|
}
|
|
477
491
|
|
|
478
492
|
/**
|
|
@@ -486,54 +500,22 @@ export function useUpdatedRef<A>(a: A): MutableRefObject<A> {
|
|
|
486
500
|
return r;
|
|
487
501
|
}
|
|
488
502
|
|
|
489
|
-
/**
|
|
490
|
-
* Checks if a control definition is readonly.
|
|
491
|
-
* @param c - The control definition to check.
|
|
492
|
-
* @returns True if the control definition is readonly, false otherwise.
|
|
493
|
-
*/
|
|
494
|
-
export function isControlReadonly(c: ControlDefinition): boolean {
|
|
495
|
-
return isDataControl(c) && !!c.readonly;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
/**
|
|
499
|
-
* Checks if a control definition is disabled.
|
|
500
|
-
* @param c - The control definition to check.
|
|
501
|
-
* @returns True if the control definition is disabled, false otherwise.
|
|
502
|
-
*/
|
|
503
|
-
export function isControlDisabled(c: ControlDefinition): boolean {
|
|
504
|
-
return isDataControl(c) && !!c.disabled;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
/**
|
|
508
|
-
* Returns the display-only render options for a control definition.
|
|
509
|
-
* @param d - The control definition to get the display-only render options for.
|
|
510
|
-
* @returns The display-only render options, or undefined if not applicable.
|
|
511
|
-
*/
|
|
512
|
-
export function getDisplayOnlyOptions(
|
|
513
|
-
d: ControlDefinition,
|
|
514
|
-
): DisplayOnlyRenderOptions | undefined {
|
|
515
|
-
return isDataControl(d) &&
|
|
516
|
-
d.renderOptions &&
|
|
517
|
-
isDisplayOnlyRenderer(d.renderOptions)
|
|
518
|
-
? d.renderOptions
|
|
519
|
-
: undefined;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
503
|
/**
|
|
523
504
|
* Cleans data for a schema based on the provided schema fields.
|
|
524
505
|
* @param v - The data to clean.
|
|
525
|
-
* @param
|
|
506
|
+
* @param schemaNode
|
|
526
507
|
* @param removeIfDefault - Flag indicating if default values should be removed.
|
|
527
508
|
* @returns The cleaned data.
|
|
528
509
|
*/
|
|
529
510
|
export function cleanDataForSchema(
|
|
530
511
|
v: { [k: string]: any } | undefined,
|
|
531
|
-
|
|
512
|
+
schemaNode: SchemaNode,
|
|
532
513
|
removeIfDefault?: boolean,
|
|
533
514
|
): any {
|
|
534
515
|
if (!v) return v;
|
|
535
|
-
const
|
|
536
|
-
const
|
|
516
|
+
const fields = schemaNode.getResolvedFields();
|
|
517
|
+
const typeField = fields.find((x) => x.isTypeField)?.field;
|
|
518
|
+
const typeValue = typeField ? v[typeField] : undefined;
|
|
537
519
|
const cleanableFields = !removeIfDefault
|
|
538
520
|
? fields.filter(
|
|
539
521
|
(x) => isCompoundField(x) || (x.onlyForTypes?.length ?? 0) > 0,
|
|
@@ -551,17 +533,17 @@ export function cleanDataForSchema(
|
|
|
551
533
|
return;
|
|
552
534
|
}
|
|
553
535
|
if (isCompoundField(x)) {
|
|
554
|
-
const
|
|
536
|
+
const childNode = schemaNode.createChildNode(x);
|
|
555
537
|
if (x.collection) {
|
|
556
538
|
if (Array.isArray(childValue)) {
|
|
557
539
|
out[x.field] = childValue.map((cv) =>
|
|
558
|
-
cleanDataForSchema(cv,
|
|
540
|
+
cleanDataForSchema(cv, childNode, removeIfDefault),
|
|
559
541
|
);
|
|
560
542
|
}
|
|
561
543
|
} else {
|
|
562
544
|
out[x.field] = cleanDataForSchema(
|
|
563
545
|
childValue,
|
|
564
|
-
|
|
546
|
+
childNode,
|
|
565
547
|
removeIfDefault,
|
|
566
548
|
);
|
|
567
549
|
}
|
|
@@ -596,6 +578,9 @@ export function getAllReferencedClasses(
|
|
|
596
578
|
isDataControl(c) && isCheckEntryClasses(c.renderOptions)
|
|
597
579
|
? c.renderOptions
|
|
598
580
|
: {};
|
|
581
|
+
const groupOptions = isGroupControl(c) ? c.groupOptions : undefined;
|
|
582
|
+
const gridClasses =
|
|
583
|
+
groupOptions && isGridRenderer(groupOptions) ? [groupOptions.rowClass] : [];
|
|
599
584
|
|
|
600
585
|
const {
|
|
601
586
|
listContainerClass,
|
|
@@ -612,6 +597,9 @@ export function getAllReferencedClasses(
|
|
|
612
597
|
c.styleClass,
|
|
613
598
|
c.layoutClass,
|
|
614
599
|
c.labelClass,
|
|
600
|
+
c.textClass,
|
|
601
|
+
c.labelTextClass,
|
|
602
|
+
...gridClasses,
|
|
615
603
|
...Object.values(go),
|
|
616
604
|
...(collectExtra?.(c) ?? []),
|
|
617
605
|
entryWrapperClass,
|
|
@@ -629,28 +617,6 @@ export function getAllReferencedClasses(
|
|
|
629
617
|
return [tc];
|
|
630
618
|
}
|
|
631
619
|
|
|
632
|
-
/**
|
|
633
|
-
* Converts a JSON path array to a string.
|
|
634
|
-
* @param jsonPath - The JSON path array to convert.
|
|
635
|
-
* @param customIndex - Optional function to customize the index format.
|
|
636
|
-
* @returns The JSON path string.
|
|
637
|
-
*/
|
|
638
|
-
export function jsonPathString(
|
|
639
|
-
jsonPath: JsonPath[],
|
|
640
|
-
customIndex?: (n: number) => string,
|
|
641
|
-
) {
|
|
642
|
-
let out = "";
|
|
643
|
-
jsonPath.forEach((v, i) => {
|
|
644
|
-
if (typeof v === "number") {
|
|
645
|
-
out += customIndex?.(v) ?? "[" + v + "]";
|
|
646
|
-
} else {
|
|
647
|
-
if (i > 0) out += ".";
|
|
648
|
-
out += v;
|
|
649
|
-
}
|
|
650
|
-
});
|
|
651
|
-
return out;
|
|
652
|
-
}
|
|
653
|
-
|
|
654
620
|
/**
|
|
655
621
|
* Finds a child control definition within a parent control definition.
|
|
656
622
|
* @param parent - The parent control definition.
|
|
@@ -796,6 +762,7 @@ export function deepMerge<A>(value: A, fallback: A): A {
|
|
|
796
762
|
deepMerge(v1, fv),
|
|
797
763
|
) as A;
|
|
798
764
|
}
|
|
765
|
+
|
|
799
766
|
/**
|
|
800
767
|
* Coerces a value to a string.
|
|
801
768
|
* @param {unknown} v - The value to coerce.
|
|
@@ -809,21 +776,6 @@ export function coerceToString(v: unknown) {
|
|
|
809
776
|
: v.toString();
|
|
810
777
|
}
|
|
811
778
|
|
|
812
|
-
/**
|
|
813
|
-
* Returns the group renderer options for a control definition.
|
|
814
|
-
* @param {ControlDefinition} def - The control definition to get the group renderer options for.
|
|
815
|
-
* @returns {GroupRenderOptions | undefined} - The group renderer options, or undefined if not applicable.
|
|
816
|
-
*/
|
|
817
|
-
export function getGroupRendererOptions(
|
|
818
|
-
def: ControlDefinition,
|
|
819
|
-
): GroupRenderOptions | undefined {
|
|
820
|
-
return isGroupControl(def)
|
|
821
|
-
? def.groupOptions
|
|
822
|
-
: isDataControl(def) && isDataGroupRenderer(def.renderOptions)
|
|
823
|
-
? def.renderOptions.groupOptions
|
|
824
|
-
: undefined;
|
|
825
|
-
}
|
|
826
|
-
|
|
827
779
|
/**
|
|
828
780
|
* Returns the group class overrides for a control definition.
|
|
829
781
|
* @param {ControlDefinition} def - The control definition to get the group class overrides for.
|
|
@@ -841,15 +793,6 @@ export function getGroupClassOverrides(def: ControlDefinition): ControlClasses {
|
|
|
841
793
|
return out;
|
|
842
794
|
}
|
|
843
795
|
|
|
844
|
-
/**
|
|
845
|
-
* Checks if a control definition is display-only.
|
|
846
|
-
* @param {ControlDefinition} def - The control definition to check.
|
|
847
|
-
* @returns {boolean} - True if the control definition is display-only, false otherwise.
|
|
848
|
-
*/
|
|
849
|
-
export function isControlDisplayOnly(def: ControlDefinition): boolean {
|
|
850
|
-
return Boolean(getGroupRendererOptions(def)?.displayOnly);
|
|
851
|
-
}
|
|
852
|
-
|
|
853
796
|
/**
|
|
854
797
|
* Combines multiple action handlers into a single handler.
|
|
855
798
|
* @param {...(ControlActionHandler | undefined)[]} handlers - The action handlers to combine.
|
|
@@ -857,10 +800,12 @@ export function isControlDisplayOnly(def: ControlDefinition): boolean {
|
|
|
857
800
|
*/
|
|
858
801
|
export function actionHandlers(
|
|
859
802
|
...handlers: (ControlActionHandler | undefined)[]
|
|
860
|
-
): ControlActionHandler {
|
|
803
|
+
): ControlActionHandler | undefined {
|
|
804
|
+
const nonNullHandlers = handlers.filter((x) => x != null);
|
|
805
|
+
if (nonNullHandlers.length === 0) return undefined;
|
|
861
806
|
return (actionId, actionData, ctx) => {
|
|
862
|
-
for (let i = 0; i <
|
|
863
|
-
const res =
|
|
807
|
+
for (let i = 0; i < nonNullHandlers.length; i++) {
|
|
808
|
+
const res = nonNullHandlers[i](actionId, actionData, ctx);
|
|
864
809
|
if (res) return res;
|
|
865
810
|
}
|
|
866
811
|
return undefined;
|
|
@@ -1051,3 +996,24 @@ export function validationVisitor(
|
|
|
1051
996
|
return undefined;
|
|
1052
997
|
};
|
|
1053
998
|
}
|
|
999
|
+
|
|
1000
|
+
export function useExpression<T>(
|
|
1001
|
+
defaultValue: T,
|
|
1002
|
+
runExpression: RunExpression,
|
|
1003
|
+
expression: EntityExpression | null | undefined,
|
|
1004
|
+
coerce: (x: any) => T,
|
|
1005
|
+
bindings?: Record<string, any>,
|
|
1006
|
+
): Control<T> {
|
|
1007
|
+
const value = useControl<T>(defaultValue);
|
|
1008
|
+
createScopedEffect((scope) => {
|
|
1009
|
+
if (expression?.type)
|
|
1010
|
+
runExpression(
|
|
1011
|
+
scope,
|
|
1012
|
+
expression,
|
|
1013
|
+
(x) => (value.value = coerce(x)),
|
|
1014
|
+
bindings,
|
|
1015
|
+
);
|
|
1016
|
+
else value.value = defaultValue;
|
|
1017
|
+
}, value);
|
|
1018
|
+
return value;
|
|
1019
|
+
}
|