@react-typed-forms/schemas 16.2.2 → 17.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.
@@ -0,0 +1,8 @@
1
+ import { Control } from "@react-typed-forms/core";
2
+ import { RenderOptions } from "@astroapps/forms-core";
3
+ import { RunExpression } from "../types";
4
+ export declare function useElementSelectedRenderer({ runExpression, renderOptions, control, }: {
5
+ runExpression: RunExpression;
6
+ renderOptions: RenderOptions;
7
+ control: Control<any>;
8
+ }): Control<boolean>;
@@ -1,6 +1,6 @@
1
1
  import { ReactElement, ReactNode } from "react";
2
2
  import { AdornmentProps, AdornmentRenderer, ArrayRendererProps, ControlLayoutProps, DataRendererProps, DisplayRendererProps, FormRenderer, GroupRendererProps, HtmlComponents, LabelRendererProps, LabelType, RenderedControl, VisibilityRendererProps } from "./controlRender";
3
- import { AccordionAdornment, ControlAdornment, IconAdornment, OptionalAdornment, RenderOptions, SetFieldAdornment } from "@astroapps/forms-core";
3
+ import { AccordionAdornment, ChildResolverFunc, ControlAdornment, FormStateNode, IconAdornment, OptionalAdornment, RenderOptions, SetFieldAdornment } from "@astroapps/forms-core";
4
4
  import { ActionRendererProps } from "./types";
5
5
  export interface DefaultRenderers {
6
6
  data: DataRendererRegistration;
@@ -26,8 +26,9 @@ export interface DataRendererRegistration {
26
26
  renderType?: string | string[];
27
27
  options?: boolean;
28
28
  collection?: boolean;
29
- match?: (props: DataRendererProps, renderOptions: RenderOptions) => boolean;
29
+ match?: (props: FormStateNode, renderOptions: RenderOptions) => boolean;
30
30
  render: (props: DataRendererProps, renderers: FormRenderer) => ReactNode | ((layout: ControlLayoutProps) => ControlLayoutProps);
31
+ resolveChildren?: ChildResolverFunc;
31
32
  }
32
33
  export interface LabelRendererRegistration {
33
34
  type: "label";
@@ -38,6 +39,7 @@ export interface ActionRendererRegistration {
38
39
  type: "action";
39
40
  actionType?: string | string[];
40
41
  render: (props: ActionRendererProps, renderers: FormRenderer) => ReactElement;
42
+ resolveChildren?: ChildResolverFunc;
41
43
  }
42
44
  export interface ArrayRendererRegistration {
43
45
  type: "array";
@@ -47,11 +49,13 @@ export interface GroupRendererRegistration {
47
49
  type: "group";
48
50
  renderType?: string | string[];
49
51
  render: (props: GroupRendererProps, renderers: FormRenderer) => ReactElement | ((layout: ControlLayoutProps) => ControlLayoutProps);
52
+ resolveChildren?: ChildResolverFunc;
50
53
  }
51
54
  export interface DisplayRendererRegistration {
52
55
  type: "display";
53
56
  renderType?: string | string[];
54
57
  render: (props: DisplayRendererProps, renderers: FormRenderer) => ReactElement;
58
+ resolveChildren?: ChildResolverFunc;
55
59
  }
56
60
  export interface AdornmentRendererRegistration {
57
61
  type: "adornment";
package/lib/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { ActionStyle, EntityExpression, FormContextData, IconPlacement, IconReference, SchemaDataNode, SchemaInterface } from "@astroapps/forms-core";
1
+ import { ActionStyle, EntityExpression, IconPlacement, IconReference, SchemaDataNode, SchemaInterface, ControlDisableType } from "@astroapps/forms-core";
2
2
  import React, { Key, ReactNode } from "react";
3
- import { CleanupScope } from "@react-typed-forms/core";
3
+ import { ChangeListenerFunc, CleanupScope } from "@react-typed-forms/core";
4
4
  /**
5
5
  * Interface representing the control data context.
6
6
  */
@@ -8,9 +8,13 @@ export interface ControlDataContext {
8
8
  schemaInterface: SchemaInterface;
9
9
  dataNode: SchemaDataNode | undefined;
10
10
  parentNode: SchemaDataNode;
11
- variables: Record<string, any>;
12
11
  }
13
- export type ControlActionHandler = (actionId: string, actionData: any, ctx: ControlDataContext) => (() => void) | undefined;
12
+ export interface ControlActionContext {
13
+ disableForm(disable: ControlDisableType): void;
14
+ runAction(action: string, actionData?: any): void | Promise<any>;
15
+ }
16
+ export declare const NoOpControlActionContext: ControlActionContext;
17
+ export type ControlActionHandler = (actionId: string, actionData: any, dataContext: ControlDataContext) => ((actionContext: ControlActionContext) => void | Promise<any>) | undefined;
14
18
  export interface ActionRendererProps {
15
19
  key?: Key;
16
20
  actionId: string;
@@ -27,5 +31,6 @@ export interface ActionRendererProps {
27
31
  disabled?: boolean;
28
32
  hidden?: boolean;
29
33
  inline?: boolean;
34
+ busy?: boolean;
30
35
  }
31
- export type RunExpression = (scope: CleanupScope, expression: EntityExpression, returnResult: (v: unknown) => void, bindings?: FormContextData) => void;
36
+ export type RunExpression = (scope: CleanupScope, expression: EntityExpression, returnResult: (v: unknown) => void, variables?: (changes: ChangeListenerFunc<any>) => Record<string, any>) => void;
package/lib/util.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CompoundField, ControlDataVisitor, ControlDefinition, DataControlDefinition, EntityExpression, FieldOption, SchemaDataNode, SchemaField, SchemaNode } from "@astroapps/forms-core";
2
2
  import { MutableRefObject } from "react";
3
- import { Control } from "@react-typed-forms/core";
3
+ import { ChangeListenerFunc, Control } from "@react-typed-forms/core";
4
4
  import { ActionRendererProps, ControlActionHandler, RunExpression } from "./types";
5
5
  /**
6
6
  * Interface representing the classes for a control.
@@ -229,4 +229,5 @@ export declare function collectDifferences(dataNode: SchemaDataNode, values: unk
229
229
  editing: number;
230
230
  };
231
231
  export declare function validationVisitor(onInvalid: (data: Control<unknown>) => void): ControlDataVisitor<any>;
232
- export declare function useExpression<T>(defaultValue: T, runExpression: RunExpression, expression: EntityExpression | null | undefined, coerce: (x: any) => T, bindings?: Record<string, any>): Control<T>;
232
+ export declare function useExpression<T>(defaultValue: T, runExpression: RunExpression, expression: EntityExpression | null | undefined, coerce: (x: any) => T, bindings?: (changes: ChangeListenerFunc<any>) => Record<string, any>): Control<T>;
233
+ export declare function setIncluded<A>(array: A[], elem: A, included: boolean): A[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-typed-forms/schemas",
3
- "version": "16.2.2",
3
+ "version": "17.0.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.cjs",
@@ -34,7 +34,7 @@
34
34
  "clsx": "^1 || ^2",
35
35
  "uuid": "^10.0.0",
36
36
  "jsonata": "^2.0.4",
37
- "@astroapps/forms-core": "^1.2.2"
37
+ "@astroapps/forms-core": "^2.0.0"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "react": "^18.2.0 || ^19",
@@ -51,7 +51,7 @@
51
51
  "@jest/globals": "^29.7.0",
52
52
  "typedoc": "^0.27.2",
53
53
  "@types/uuid": "^10.0.0",
54
- "@types/react": "^18.2.28",
54
+ "@types/react": "^18.2.28 || ^19",
55
55
  "markdown-magic": "^2.6.1",
56
56
  "microbundle": "^0.15.1",
57
57
  "nswag": "^13.18.2",
@@ -61,8 +61,8 @@
61
61
  },
62
62
  "gitHead": "698e16cd3ab31b7dd0528fc76536f4d3205ce8c6",
63
63
  "scripts": {
64
- "build": "rimraf ./lib/ node_modules/.cache && microbundle -f modern,cjs --no-compress --jsxImportSource=react",
65
- "watch": "microbundle -w -f modern,cjs --no-compress --jsxImportSource=react",
64
+ "build": "rimraf ./lib/ node_modules/.cache && microbundle -f modern,cjs --no-compress --jsx React --jsxImportSource=react",
65
+ "watch": "microbundle -f modern,cjs --no-compress --jsx React --jsxImportSource=react",
66
66
  "test": "jest --coverage",
67
67
  "play": "tsx test/play.ts",
68
68
  "update-readme": "md-magic --path README.md",
@@ -9,22 +9,24 @@ import {
9
9
  } from "./controlRender";
10
10
  import React, {
11
11
  FC,
12
+ MutableRefObject,
12
13
  useCallback,
13
14
  useEffect,
14
15
  useMemo,
15
- useRef,
16
- useState,
17
16
  } from "react";
18
17
  import {
19
18
  ControlDefinition,
20
- ControlState,
21
- createFormState,
19
+ ControlDisableType,
20
+ createFormStateNode,
22
21
  createSchemaDataNode,
23
22
  createSchemaTree,
23
+ defaultEvaluators,
24
24
  defaultSchemaInterface,
25
+ FormGlobalOptions,
25
26
  FormNode,
26
- FormState,
27
- isDataControl,
27
+ FormNodeOptions,
28
+ FormNodeUi,
29
+ FormStateNode,
28
30
  JsonPath,
29
31
  legacyFormNode,
30
32
  SchemaDataNode,
@@ -44,6 +46,7 @@ export interface RenderFormProps {
44
46
  form: FormNode;
45
47
  renderer: FormRenderer;
46
48
  options?: ControlRenderOptions;
49
+ stateRef?: MutableRefObject<FormStateNode | null>;
47
50
  }
48
51
 
49
52
  /* @trackControls */
@@ -52,28 +55,64 @@ export function RenderForm({
52
55
  form,
53
56
  renderer,
54
57
  options = {},
58
+ stateRef,
55
59
  }: RenderFormProps) {
60
+ const { readonly, disabled, displayOnly, hidden, variables, clearHidden } =
61
+ options;
56
62
  const schemaInterface = options.schemaInterface ?? defaultSchemaInterface;
57
- const [formState, setFormState] = useState(
58
- () => options?.formState ?? createFormState(schemaInterface),
59
- );
60
- let effects: (() => void)[] | undefined = [];
61
- const runAsync = (cb: () => void) => {
62
- if (effects) effects.push(cb);
63
- else cb();
63
+ const { runAsync } = useAsyncRunner();
64
+ const globals: FormGlobalOptions = {
65
+ runAsync,
66
+ schemaInterface,
67
+ evalExpression: (e, ctx) => defaultEvaluators[e.type]?.(e, ctx),
68
+ resolveChildren: renderer.resolveChildren,
69
+ clearHidden: !!clearHidden,
64
70
  };
65
- const state = formState.getControlState(data, form, options, runAsync);
66
-
71
+ const state = useMemo(
72
+ () =>
73
+ createFormStateNode(form, data, globals, {
74
+ forceReadonly: !!readonly,
75
+ forceDisabled: !!disabled,
76
+ variables,
77
+ forceHidden: !!hidden,
78
+ }),
79
+ [form.id],
80
+ );
81
+ state.globals.value = globals;
82
+ state.options.setValue((x) => ({
83
+ variables,
84
+ forceHidden: hidden ?? x.forceHidden,
85
+ forceDisabled: disabled ?? x.forceDisabled,
86
+ forceReadonly: readonly ?? x.forceReadonly,
87
+ }));
88
+ if (stateRef) stateRef.current = state;
67
89
  useEffect(() => {
68
- if (!options?.formState) {
69
- return () => formState.cleanup();
70
- }
71
- }, [formState, options?.formState]);
72
-
73
- const definition = state.definition;
90
+ return () => {
91
+ state.cleanup();
92
+ };
93
+ }, [state]);
94
+ return <RenderFormNode node={state} renderer={renderer} options={options} />;
95
+ }
74
96
 
75
- const visible = !state.hidden;
97
+ export interface RenderFormNodeProps {
98
+ node: FormStateNode;
99
+ renderer: FormRenderer;
100
+ options?: ControlRenderOptions;
101
+ }
76
102
 
103
+ /* @trackControls */
104
+ export function RenderFormNode({
105
+ node: state,
106
+ renderer,
107
+ options = {},
108
+ }: RenderFormNodeProps) {
109
+ useEffect(() => {
110
+ state.attachUi(new DefaultFormNodeUi(state));
111
+ }, [state]);
112
+ const { runAsync } = useAsyncRunner();
113
+ const schemaInterface = state.schemaInterface;
114
+ const definition = state.definition;
115
+ const visible = state.visible;
77
116
  const visibility = useControl<Visibility | undefined>(() =>
78
117
  visible != null
79
118
  ? {
@@ -82,13 +121,14 @@ export function RenderForm({
82
121
  }
83
122
  : undefined,
84
123
  );
85
- visibility.fields.visible.value = visible;
124
+ if (visible != null) {
125
+ visibility.fields.visible.value = visible;
126
+ }
86
127
 
87
128
  const dataContext: ControlDataContext = {
88
129
  schemaInterface: state.schemaInterface,
89
130
  dataNode: state.dataNode,
90
- parentNode: data,
91
- variables: state.variables,
131
+ parentNode: state.parent,
92
132
  };
93
133
 
94
134
  const adornments =
@@ -96,7 +136,7 @@ export function RenderForm({
96
136
  renderer.renderAdornment({
97
137
  adornment: x,
98
138
  dataContext,
99
- formOptions: state,
139
+ formNode: state,
100
140
  }),
101
141
  ) ?? [];
102
142
 
@@ -108,41 +148,35 @@ export function RenderForm({
108
148
  textClass,
109
149
  ...inheritableOptions
110
150
  } = options;
111
- const { readonly, hidden, disabled, variables } = state;
151
+ const { readonly, visible: vis, disabled, variables } = state;
112
152
  const childOptions: ControlRenderOptions = {
113
153
  ...inheritableOptions,
114
154
  readonly,
115
155
  disabled,
116
156
  variables,
117
- formState,
118
- hidden,
157
+ hidden: vis === false,
119
158
  };
120
159
 
121
160
  const labelAndChildren = renderControlLayout({
122
- formNode: form,
161
+ formNode: state,
123
162
  renderer,
124
- state,
125
- renderChild: (k, child, options) => {
163
+ renderChild: (child, options) => {
126
164
  const overrideClasses = getGroupClassOverrides(definition);
127
- const { parentDataNode, actionOnClick, variables, ...renderOptions } =
128
- options ?? {};
129
- const dContext = parentDataNode ?? dataContext.dataNode ?? data;
165
+ const { actionOnClick, ...renderOptions } = options ?? {};
130
166
  const allChildOptions = {
131
167
  ...childOptions,
132
168
  ...overrideClasses,
133
169
  ...renderOptions,
134
- variables: { ...childOptions.variables, ...variables },
135
170
  actionOnClick: actionHandlers(
136
171
  actionOnClick,
137
172
  childOptions.actionOnClick,
138
173
  ),
139
174
  };
140
175
  return (
141
- <RenderForm
142
- key={k}
143
- form={child}
176
+ <RenderFormNode
177
+ key={child.childKey}
178
+ node={child}
144
179
  renderer={renderer}
145
- data={dContext}
146
180
  options={allChildOptions}
147
181
  />
148
182
  );
@@ -150,32 +184,22 @@ export function RenderForm({
150
184
  inline: options?.inline,
151
185
  displayOnly: options?.displayOnly,
152
186
  createDataProps: defaultDataProps,
153
- formOptions: state,
154
187
  dataContext,
155
188
  control: dataContext.dataNode?.control,
156
189
  schemaInterface,
157
- style: state.style,
158
- allowedOptions: state.allowedOptions,
190
+ style: state.resolved.style,
159
191
  customDisplay: options.customDisplay,
160
192
  actionOnClick: options.actionOnClick,
161
193
  styleClass: styleClass,
162
194
  labelClass: labelClass,
163
195
  labelTextClass: labelTextClass,
164
196
  textClass: textClass,
165
- getChildState(child: FormNode, parent?: SchemaDataNode): ControlState {
166
- return formState.getControlState(
167
- parent ?? state.dataNode ?? data,
168
- child,
169
- childOptions,
170
- runAsync,
171
- );
172
- },
173
197
  runExpression: (scope, expr, returnResult) => {
174
198
  if (expr?.type) {
175
- formState.evalExpression(expr, {
176
- scope,
177
- dataNode: data,
199
+ defaultEvaluators[expr.type](expr, {
200
+ dataNode: state.parent,
178
201
  schemaInterface,
202
+ scope,
179
203
  returnResult,
180
204
  runAsync,
181
205
  });
@@ -186,23 +210,15 @@ export function RenderForm({
186
210
  ...labelAndChildren,
187
211
  adornments,
188
212
  className: rendererClass(options.layoutClass, definition.layoutClass),
189
- style: state.layoutStyle,
213
+ style: state.resolved.layoutStyle,
190
214
  };
191
215
  const renderedControl = renderer.renderLayout(
192
216
  options.adjustLayout?.(dataContext, layoutProps) ?? layoutProps,
193
217
  );
194
- const rendered = renderer.renderVisibility({
218
+ return renderer.renderVisibility({
195
219
  visibility,
196
220
  ...renderedControl,
197
221
  });
198
- useEffect(() => {
199
- if (effects) {
200
- const toRun = effects;
201
- effects = undefined;
202
- toRun.forEach((cb) => cb());
203
- }
204
- }, [effects]);
205
- return rendered;
206
222
  }
207
223
 
208
224
  /**
@@ -319,3 +335,53 @@ export function useControlRenderer(
319
335
  [r],
320
336
  );
321
337
  }
338
+
339
+ export function useAsyncRunner(): {
340
+ runAsync: (cb: () => void) => void;
341
+ } {
342
+ let effects: (() => void)[] | undefined = [];
343
+ const runAsync = (cb: () => void) => {
344
+ if (effects) effects.push(cb);
345
+ else cb();
346
+ };
347
+ useEffect(() => {
348
+ if (effects) {
349
+ const toRun = effects;
350
+ effects = undefined;
351
+ toRun.forEach((cb) => cb());
352
+ }
353
+ }, [effects]);
354
+
355
+ return {
356
+ runAsync,
357
+ };
358
+ }
359
+
360
+ export class DefaultFormNodeUi implements FormNodeUi {
361
+ constructor(protected node: FormStateNode) {}
362
+ ensureVisible() {
363
+ this.node.parentNode?.ui.ensureChildVisible(this.node.childIndex);
364
+ }
365
+ ensureChildVisible(childIndex: number) {
366
+ this.ensureVisible();
367
+ }
368
+ getDisabler(type: ControlDisableType): () => () => void {
369
+ if (type === ControlDisableType.Self) {
370
+ return () => {
371
+ const old = !!this.node.forceDisabled;
372
+ this.node.setForceDisabled(true);
373
+ return () => {
374
+ this.node.setForceDisabled(old);
375
+ };
376
+ };
377
+ }
378
+ if (type === ControlDisableType.Global) {
379
+ let topLevel = this.node;
380
+ while (topLevel.parentNode) {
381
+ topLevel = topLevel.parentNode;
382
+ }
383
+ return topLevel.ui.getDisabler(ControlDisableType.Self);
384
+ }
385
+ return () => () => {};
386
+ }
387
+ }
@@ -1,201 +1,18 @@
1
1
  import {
2
- AccordionAdornment,
3
- ActionControlDefinition,
4
- AutocompleteRenderOptions,
5
- CheckListRenderOptions,
6
- ControlAdornmentType,
7
2
  ControlDefinition,
8
- ControlDefinitionType,
9
- DataControlDefinition,
10
- DataExpression,
11
- DataMatchExpression,
12
- DataRenderType,
13
- DateValidator,
14
- DisplayControlDefinition,
15
- DisplayDataType,
16
- DisplayOnlyRenderOptions,
17
- DynamicProperty,
18
- DynamicPropertyType,
19
- EntityExpression,
20
- ExpressionType,
3
+ emptyGroupDefinition,
21
4
  GroupedControlsDefinition,
22
- GroupRenderType,
23
- HtmlDisplay,
24
- JsonataExpression,
25
- JsonataRenderOptions,
26
- JsonataValidator,
27
- LengthValidator,
5
+ mergeFields,
28
6
  mergeOption,
29
- RadioButtonRenderOptions,
30
- RenderOptions,
7
+ resolveSchemas,
31
8
  SchemaField,
32
9
  SchemaMap,
33
10
  SchemaNode,
34
- TextDisplay,
35
- TextfieldRenderOptions,
36
- ValidatorType,
37
11
  } from "@astroapps/forms-core";
38
12
  import { useMemo } from "react";
39
13
  import { addMissingControls } from "./util";
40
- import { mergeFields, resolveSchemas } from "@astroapps/forms-core";
41
14
  import { ActionRendererProps } from "./types";
42
15
 
43
- export function dataControl(
44
- field: string,
45
- title?: string | null,
46
- options?: Partial<DataControlDefinition>,
47
- ): DataControlDefinition {
48
- return { type: ControlDefinitionType.Data, field, title, ...options };
49
- }
50
-
51
- export function validatorOptions<A extends { type: string }>(
52
- type: ValidatorType,
53
- ): (options: Omit<A, "type">) => A {
54
- return (o) => ({ type, ...o }) as A;
55
- }
56
-
57
- export function adornmentOptions<A extends { type: string }>(
58
- type: ControlAdornmentType,
59
- ): (options: Omit<A, "type">) => A {
60
- return (o) => ({ type, ...o }) as A;
61
- }
62
-
63
- export function renderOptionsFor<A extends RenderOptions>(
64
- type: DataRenderType,
65
- ): (options: Omit<A, "type">) => { renderOptions: A } {
66
- return (o) => ({ renderOptions: { type, ...o } as A });
67
- }
68
-
69
- export const autocompleteOptions = renderOptionsFor<AutocompleteRenderOptions>(
70
- DataRenderType.Autocomplete,
71
- );
72
-
73
- export const checkListOptions = renderOptionsFor<CheckListRenderOptions>(
74
- DataRenderType.CheckList,
75
- );
76
-
77
- export const radioButtonOptions = renderOptionsFor<RadioButtonRenderOptions>(
78
- DataRenderType.Radio,
79
- );
80
-
81
- export const lengthValidatorOptions = validatorOptions<LengthValidator>(
82
- ValidatorType.Length,
83
- );
84
-
85
- export const jsonataValidatorOptions = validatorOptions<JsonataValidator>(
86
- ValidatorType.Jsonata,
87
- );
88
-
89
- export const dateValidatorOptions = validatorOptions<DateValidator>(
90
- ValidatorType.Date,
91
- );
92
-
93
- export const accordionOptions = adornmentOptions<AccordionAdornment>(
94
- ControlAdornmentType.Accordion,
95
- );
96
-
97
- export const textfieldOptions = renderOptionsFor<TextfieldRenderOptions>(
98
- DataRenderType.Textfield,
99
- );
100
-
101
- export const displayOnlyOptions = renderOptionsFor<DisplayOnlyRenderOptions>(
102
- DataRenderType.DisplayOnly,
103
- );
104
-
105
- export const jsonataOptions = renderOptionsFor<JsonataRenderOptions>(
106
- DataRenderType.Jsonata,
107
- );
108
-
109
- export function textDisplayControl(
110
- text: string,
111
- options?: Partial<DisplayControlDefinition>,
112
- ): DisplayControlDefinition {
113
- return {
114
- type: ControlDefinitionType.Display,
115
- displayData: { type: DisplayDataType.Text, text } as TextDisplay,
116
- ...options,
117
- };
118
- }
119
-
120
- export function htmlDisplayControl(
121
- html: string,
122
- options?: Partial<DisplayControlDefinition>,
123
- ): DisplayControlDefinition {
124
- return {
125
- type: ControlDefinitionType.Display,
126
- displayData: { type: DisplayDataType.Html, html } as HtmlDisplay,
127
- ...options,
128
- };
129
- }
130
-
131
- export function dynamicDefaultValue(expr: EntityExpression): DynamicProperty {
132
- return { type: DynamicPropertyType.DefaultValue, expr };
133
- }
134
-
135
- export function dynamicReadonly(expr: EntityExpression): DynamicProperty {
136
- return { type: DynamicPropertyType.Readonly, expr };
137
- }
138
-
139
- export function dynamicVisibility(expr: EntityExpression): DynamicProperty {
140
- return { type: DynamicPropertyType.Visible, expr };
141
- }
142
-
143
- export function dynamicDisabled(expr: EntityExpression): DynamicProperty {
144
- return { type: DynamicPropertyType.Disabled, expr };
145
- }
146
-
147
- export function fieldExpr(field: string): DataExpression {
148
- return { type: ExpressionType.Data, field };
149
- }
150
-
151
- export function fieldEqExpr(field: string, value: any): DataMatchExpression {
152
- return { type: ExpressionType.DataMatch, field, value };
153
- }
154
- export function jsonataExpr(expression: string): JsonataExpression {
155
- return { type: ExpressionType.Jsonata, expression };
156
- }
157
-
158
- export function groupedControl(
159
- children: ControlDefinition[],
160
- title?: string,
161
- options?: Partial<GroupedControlsDefinition>,
162
- ): GroupedControlsDefinition {
163
- return {
164
- type: ControlDefinitionType.Group,
165
- children,
166
- title,
167
- groupOptions: { type: "Standard", hideTitle: !title },
168
- ...options,
169
- };
170
- }
171
- export function compoundControl(
172
- field: string,
173
- title: string | undefined,
174
- children: ControlDefinition[],
175
- options?: Partial<DataControlDefinition>,
176
- ): DataControlDefinition {
177
- return {
178
- type: ControlDefinitionType.Data,
179
- field,
180
- children,
181
- title,
182
- renderOptions: { type: "Standard" },
183
- ...options,
184
- };
185
- }
186
-
187
- export function actionControl(
188
- actionText: string,
189
- actionId: string,
190
- options?: Partial<ActionControlDefinition>,
191
- ): ActionControlDefinition {
192
- return {
193
- type: ControlDefinitionType.Action,
194
- title: actionText,
195
- actionId,
196
- ...options,
197
- };
198
- }
199
16
  export function createAction(
200
17
  actionId: string,
201
18
  onClick: () => void,
@@ -210,12 +27,6 @@ export function createAction(
210
27
  };
211
28
  }
212
29
 
213
- export const emptyGroupDefinition: GroupedControlsDefinition = {
214
- type: ControlDefinitionType.Group,
215
- children: [],
216
- groupOptions: { type: GroupRenderType.Standard, hideTitle: true },
217
- };
218
-
219
30
  export function useControlDefinitionForSchema(
220
31
  sf: SchemaField[],
221
32
  definition: GroupedControlsDefinition = emptyGroupDefinition,
@@ -235,7 +46,7 @@ export interface EditorGroup {
235
46
  }
236
47
 
237
48
  export interface CustomRenderOptions {
238
- value: string;
49
+ value?: string;
239
50
  name: string;
240
51
  fields?: SchemaField[];
241
52
  groups?: EditorGroup[];
@@ -250,6 +61,8 @@ export type ControlDefinitionExtension = {
250
61
  SchemaValidator?: CustomRenderOptions | CustomRenderOptions[];
251
62
  DisplayData?: CustomRenderOptions | CustomRenderOptions[];
252
63
  IconReference?: CustomRenderOptions | CustomRenderOptions[];
64
+ ControlDefinition?: CustomRenderOptions | CustomRenderOptions[];
65
+ SchemaField?: CustomRenderOptions | CustomRenderOptions[];
253
66
  };
254
67
 
255
68
  export function applyExtensionToSchema<A extends SchemaMap>(