@react-typed-forms/schemas 1.0.0-dev.16 → 1.0.0-dev.18
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/package-deps_build.json +2 -2
- package/.rush/temp/shrinkwrap-deps.json +5 -3
- package/lib/controlRender.d.ts +126 -100
- package/lib/hooks.d.ts +10 -9
- package/lib/index.d.ts +7 -5
- package/lib/index.js +1169 -3044
- package/lib/index.js.map +1 -1
- package/lib/renderers.d.ts +153 -0
- package/lib/schemaBuilder.d.ts +87 -87
- package/lib/tailwind.d.ts +2 -0
- package/lib/types.d.ts +272 -234
- package/lib/util.d.ts +6 -3
- package/package.json +10 -7
- package/src/controlRender.tsx +187 -176
- package/src/hooks.tsx +425 -0
- package/src/index.ts +2 -0
- package/src/renderers.tsx +855 -0
- package/src/tailwind.tsx +21 -0
- package/src/types.ts +56 -9
- package/src/util.ts +5 -1
- package/src/hooks.ts +0 -173
package/src/tailwind.tsx
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { DefaultRendererOptions } from "./renderers";
|
|
3
|
+
|
|
4
|
+
export const defaultTailwindTheme: DefaultRendererOptions = {
|
|
5
|
+
label: {
|
|
6
|
+
className: "flex flex-col",
|
|
7
|
+
groupLabelClass: "font-bold",
|
|
8
|
+
requiredElement: <span className="text-red-500"> *</span>,
|
|
9
|
+
},
|
|
10
|
+
array: {
|
|
11
|
+
removableClass: "grid grid-cols-[1fr_auto] items-center gap-x-2",
|
|
12
|
+
childClass: "grow",
|
|
13
|
+
},
|
|
14
|
+
group: {
|
|
15
|
+
standardClassName: "space-y-4",
|
|
16
|
+
gridClassName: "gap-x-2 gap-y-4",
|
|
17
|
+
},
|
|
18
|
+
action: {
|
|
19
|
+
className: "bg-primary rounded-lg p-3 text-white",
|
|
20
|
+
},
|
|
21
|
+
};
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { DataControlProperties } from "./controlRender";
|
|
2
|
-
|
|
3
1
|
export interface SchemaField {
|
|
4
2
|
type: string;
|
|
5
3
|
field: string;
|
|
@@ -13,6 +11,7 @@ export interface SchemaField {
|
|
|
13
11
|
isTypeField?: boolean | null;
|
|
14
12
|
searchable?: boolean | null;
|
|
15
13
|
options?: FieldOption[] | null;
|
|
14
|
+
validators?: SchemaValidator[] | null;
|
|
16
15
|
/**
|
|
17
16
|
* @deprecated Use options directly
|
|
18
17
|
*/
|
|
@@ -114,9 +113,17 @@ export interface ControlAdornment {
|
|
|
114
113
|
type: string;
|
|
115
114
|
}
|
|
116
115
|
|
|
116
|
+
export enum AdornmentPlacement {
|
|
117
|
+
ControlStart = "ControlStart",
|
|
118
|
+
ControlEnd = "ControlEnd",
|
|
119
|
+
LabelStart = "LabelStart",
|
|
120
|
+
LabelEnd = "LabelEnd",
|
|
121
|
+
}
|
|
122
|
+
|
|
117
123
|
export enum ControlAdornmentType {
|
|
118
124
|
Tooltip = "Tooltip",
|
|
119
125
|
Accordion = "Accordion",
|
|
126
|
+
HelpText = "HelpText",
|
|
120
127
|
}
|
|
121
128
|
|
|
122
129
|
export interface TooltipAdornment extends ControlAdornment {
|
|
@@ -130,6 +137,12 @@ export interface AccordionAdornment extends ControlAdornment {
|
|
|
130
137
|
defaultExpanded: boolean;
|
|
131
138
|
}
|
|
132
139
|
|
|
140
|
+
export interface HelpTextAdornment extends ControlAdornment {
|
|
141
|
+
type: ControlAdornmentType.HelpText;
|
|
142
|
+
helpText: string;
|
|
143
|
+
placement: AdornmentPlacement;
|
|
144
|
+
}
|
|
145
|
+
|
|
133
146
|
export interface DataControlDefinition extends ControlDefinition {
|
|
134
147
|
type: ControlDefinitionType.Data;
|
|
135
148
|
field: string;
|
|
@@ -137,6 +150,7 @@ export interface DataControlDefinition extends ControlDefinition {
|
|
|
137
150
|
renderOptions?: RenderOptions | null;
|
|
138
151
|
defaultValue?: any;
|
|
139
152
|
readonly?: boolean | null;
|
|
153
|
+
validators?: SchemaValidator[] | null;
|
|
140
154
|
}
|
|
141
155
|
|
|
142
156
|
export interface RenderOptions {
|
|
@@ -153,6 +167,8 @@ export enum DataRenderType {
|
|
|
153
167
|
Synchronised = "Synchronised",
|
|
154
168
|
IconSelector = "IconSelector",
|
|
155
169
|
DateTime = "DateTime",
|
|
170
|
+
Checkbox = "Checkbox",
|
|
171
|
+
Dropdown = "Dropdown",
|
|
156
172
|
}
|
|
157
173
|
|
|
158
174
|
export interface RadioButtonRenderOptions extends RenderOptions {
|
|
@@ -270,26 +286,51 @@ export interface ActionControlDefinition extends ControlDefinition {
|
|
|
270
286
|
actionId: string;
|
|
271
287
|
}
|
|
272
288
|
|
|
289
|
+
export enum ValidatorType {
|
|
290
|
+
Jsonata = "Jsonata",
|
|
291
|
+
Date = "Date",
|
|
292
|
+
}
|
|
293
|
+
export interface SchemaValidator {
|
|
294
|
+
type: string;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export interface JsonataValidator extends SchemaValidator {
|
|
298
|
+
type: ValidatorType.Jsonata;
|
|
299
|
+
expression: string;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export enum DateComparison {
|
|
303
|
+
NotBefore = "NotBefore",
|
|
304
|
+
NotAfter = "NotAfter",
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export interface DateValidator extends SchemaValidator {
|
|
308
|
+
type: ValidatorType.Date;
|
|
309
|
+
comparison: DateComparison;
|
|
310
|
+
fixedDate?: string | null;
|
|
311
|
+
daysFromCurrent?: number | null;
|
|
312
|
+
}
|
|
313
|
+
|
|
273
314
|
export function isDataControlDefinition(
|
|
274
|
-
x: ControlDefinition
|
|
315
|
+
x: ControlDefinition,
|
|
275
316
|
): x is DataControlDefinition {
|
|
276
317
|
return x.type === ControlDefinitionType.Data;
|
|
277
318
|
}
|
|
278
319
|
|
|
279
320
|
export function isGroupControlsDefinition(
|
|
280
|
-
x: ControlDefinition
|
|
321
|
+
x: ControlDefinition,
|
|
281
322
|
): x is GroupedControlsDefinition {
|
|
282
323
|
return x.type === ControlDefinitionType.Group;
|
|
283
324
|
}
|
|
284
325
|
|
|
285
326
|
export function isDisplayControlsDefinition(
|
|
286
|
-
x: ControlDefinition
|
|
327
|
+
x: ControlDefinition,
|
|
287
328
|
): x is DisplayControlDefinition {
|
|
288
329
|
return x.type === ControlDefinitionType.Display;
|
|
289
330
|
}
|
|
290
331
|
|
|
291
332
|
export function isActionControlsDefinition(
|
|
292
|
-
x: ControlDefinition
|
|
333
|
+
x: ControlDefinition,
|
|
293
334
|
): x is ActionControlDefinition {
|
|
294
335
|
return x.type === ControlDefinitionType.Action;
|
|
295
336
|
}
|
|
@@ -304,7 +345,7 @@ export interface ControlVisitor<A> {
|
|
|
304
345
|
export function visitControlDefinition<A>(
|
|
305
346
|
x: ControlDefinition,
|
|
306
347
|
visitor: ControlVisitor<A>,
|
|
307
|
-
defaultValue: (c: ControlDefinition) => A
|
|
348
|
+
defaultValue: (c: ControlDefinition) => A,
|
|
308
349
|
): A {
|
|
309
350
|
switch (x.type) {
|
|
310
351
|
case ControlDefinitionType.Action:
|
|
@@ -322,14 +363,14 @@ export function visitControlDefinition<A>(
|
|
|
322
363
|
|
|
323
364
|
export function dataControl(
|
|
324
365
|
field: string,
|
|
325
|
-
options?: Partial<DataControlDefinition
|
|
366
|
+
options?: Partial<DataControlDefinition>,
|
|
326
367
|
): DataControlDefinition {
|
|
327
368
|
return { type: ControlDefinitionType.Data, field, ...options };
|
|
328
369
|
}
|
|
329
370
|
|
|
330
371
|
export function fieldValueExpr(
|
|
331
372
|
field: string,
|
|
332
|
-
value: any
|
|
373
|
+
value: any,
|
|
333
374
|
): FieldValueExpression {
|
|
334
375
|
return { type: ExpressionType.FieldValue, field, value };
|
|
335
376
|
}
|
|
@@ -337,3 +378,9 @@ export function fieldValueExpr(
|
|
|
337
378
|
export function visibility(expr: EntityExpression): DynamicProperty {
|
|
338
379
|
return { type: DynamicPropertyType.Visible, expr };
|
|
339
380
|
}
|
|
381
|
+
|
|
382
|
+
export function isGridRenderer(
|
|
383
|
+
options: GroupRenderOptions,
|
|
384
|
+
): options is GridRenderer {
|
|
385
|
+
return options.type === GroupRenderType.Grid;
|
|
386
|
+
}
|
package/src/util.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SchemaField } from "./types";
|
|
1
|
+
import { FieldOption, SchemaField } from "./types";
|
|
2
2
|
|
|
3
3
|
export function fieldHasTag(field: SchemaField, tag: string) {
|
|
4
4
|
return Boolean(field.tags?.includes(tag));
|
|
@@ -7,3 +7,7 @@ export function fieldHasTag(field: SchemaField, tag: string) {
|
|
|
7
7
|
export function fieldDisplayName(field: SchemaField) {
|
|
8
8
|
return field.displayName ?? field.field;
|
|
9
9
|
}
|
|
10
|
+
|
|
11
|
+
export function hasOptions(o: { options: FieldOption[] | undefined | null }) {
|
|
12
|
+
return (o.options?.length ?? 0) > 0;
|
|
13
|
+
}
|
package/src/hooks.ts
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ActionControlDefinition,
|
|
3
|
-
ControlDefinition,
|
|
4
|
-
DataControlDefinition,
|
|
5
|
-
DynamicPropertyType,
|
|
6
|
-
EntityExpression,
|
|
7
|
-
ExpressionType,
|
|
8
|
-
FieldOption,
|
|
9
|
-
FieldValueExpression,
|
|
10
|
-
SchemaField,
|
|
11
|
-
} from "./types";
|
|
12
|
-
import {
|
|
13
|
-
ActionControlProperties,
|
|
14
|
-
controlForField,
|
|
15
|
-
DataControlProperties,
|
|
16
|
-
ExpressionHook,
|
|
17
|
-
fieldForControl,
|
|
18
|
-
findField,
|
|
19
|
-
FormEditHooks,
|
|
20
|
-
FormEditState,
|
|
21
|
-
isGroupControl,
|
|
22
|
-
isScalarField,
|
|
23
|
-
} from "./controlRender";
|
|
24
|
-
import { useEffect, useMemo } from "react";
|
|
25
|
-
import { Control, newControl } from "@react-typed-forms/core";
|
|
26
|
-
|
|
27
|
-
export function useDefaultValue(
|
|
28
|
-
definition: DataControlDefinition,
|
|
29
|
-
field: SchemaField,
|
|
30
|
-
formState: FormEditState,
|
|
31
|
-
useExpression: ExpressionHook
|
|
32
|
-
) {
|
|
33
|
-
const valueExpression = definition.dynamic?.find(
|
|
34
|
-
(x) => x.type === DynamicPropertyType.DefaultValue
|
|
35
|
-
);
|
|
36
|
-
if (valueExpression) {
|
|
37
|
-
return useExpression(valueExpression.expr, formState);
|
|
38
|
-
}
|
|
39
|
-
return field.defaultValue;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function useIsControlVisible(
|
|
43
|
-
definition: ControlDefinition,
|
|
44
|
-
formState: FormEditState,
|
|
45
|
-
useExpression: ExpressionHook
|
|
46
|
-
) {
|
|
47
|
-
const visibleExpression = definition.dynamic?.find(
|
|
48
|
-
(x) => x.type === DynamicPropertyType.Visible
|
|
49
|
-
);
|
|
50
|
-
if (visibleExpression && visibleExpression.expr) {
|
|
51
|
-
return Boolean(useExpression(visibleExpression.expr, formState));
|
|
52
|
-
}
|
|
53
|
-
const schemaFields = formState.fields;
|
|
54
|
-
|
|
55
|
-
const { typeControl, compoundField } = useMemo(() => {
|
|
56
|
-
const typeField = schemaFields.find(
|
|
57
|
-
(x) => isScalarField(x) && x.isTypeField
|
|
58
|
-
) as SchemaField | undefined;
|
|
59
|
-
|
|
60
|
-
const typeControl = ((typeField &&
|
|
61
|
-
formState.data.fields?.[typeField.field]) ??
|
|
62
|
-
newControl(undefined)) as Control<string | undefined>;
|
|
63
|
-
const compoundField =
|
|
64
|
-
isGroupControl(definition) && definition.compoundField
|
|
65
|
-
? formState.data.fields[definition.compoundField]
|
|
66
|
-
: undefined;
|
|
67
|
-
return { typeControl, compoundField };
|
|
68
|
-
}, [schemaFields, formState.data]);
|
|
69
|
-
|
|
70
|
-
const fieldName = fieldForControl(definition);
|
|
71
|
-
const onlyForTypes = (
|
|
72
|
-
fieldName ? findField(schemaFields, fieldName) : undefined
|
|
73
|
-
)?.onlyForTypes;
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
(!compoundField || compoundField.value != null) &&
|
|
77
|
-
(!onlyForTypes ||
|
|
78
|
-
onlyForTypes.length === 0 ||
|
|
79
|
-
Boolean(typeControl.value && onlyForTypes.includes(typeControl.value)))
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
export function getDefaultScalarControlProperties(
|
|
83
|
-
definition: DataControlDefinition,
|
|
84
|
-
field: SchemaField,
|
|
85
|
-
visible: boolean,
|
|
86
|
-
defaultValue: any,
|
|
87
|
-
control: Control<any>,
|
|
88
|
-
readonly?: boolean
|
|
89
|
-
): DataControlProperties {
|
|
90
|
-
return {
|
|
91
|
-
defaultValue,
|
|
92
|
-
options: getOptionsForScalarField(field),
|
|
93
|
-
required: definition.required ?? false,
|
|
94
|
-
visible,
|
|
95
|
-
readonly: readonly ?? definition.readonly ?? false,
|
|
96
|
-
control,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function getOptionsForScalarField(
|
|
101
|
-
field: SchemaField
|
|
102
|
-
): FieldOption[] | undefined | null {
|
|
103
|
-
const opts = field.options ?? field.restrictions?.options;
|
|
104
|
-
if (opts?.length ?? 0 > 0) {
|
|
105
|
-
return opts;
|
|
106
|
-
}
|
|
107
|
-
return undefined;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export const defaultExpressionHook: ExpressionHook = (
|
|
111
|
-
expr: EntityExpression,
|
|
112
|
-
formState: FormEditState
|
|
113
|
-
) => {
|
|
114
|
-
switch (expr.type) {
|
|
115
|
-
case ExpressionType.FieldValue:
|
|
116
|
-
const fvExpr = expr as FieldValueExpression;
|
|
117
|
-
return controlForField(fvExpr.field, formState).value === fvExpr.value;
|
|
118
|
-
default:
|
|
119
|
-
return undefined;
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
export function createFormEditHooks(
|
|
124
|
-
useExpression: ExpressionHook
|
|
125
|
-
): FormEditHooks {
|
|
126
|
-
return {
|
|
127
|
-
useExpression,
|
|
128
|
-
useDataProperties(
|
|
129
|
-
formState: FormEditState,
|
|
130
|
-
definition: DataControlDefinition,
|
|
131
|
-
field: SchemaField
|
|
132
|
-
): DataControlProperties {
|
|
133
|
-
const visible = useIsControlVisible(definition, formState, useExpression);
|
|
134
|
-
const defaultValue = useDefaultValue(
|
|
135
|
-
definition,
|
|
136
|
-
field,
|
|
137
|
-
formState,
|
|
138
|
-
useExpression
|
|
139
|
-
);
|
|
140
|
-
const scalarControl = formState.data.fields[field.field];
|
|
141
|
-
|
|
142
|
-
useEffect(() => {
|
|
143
|
-
if (!visible) scalarControl.value = null;
|
|
144
|
-
else if (scalarControl.current.value == null) {
|
|
145
|
-
scalarControl.value = defaultValue;
|
|
146
|
-
}
|
|
147
|
-
}, [visible, defaultValue]);
|
|
148
|
-
return getDefaultScalarControlProperties(
|
|
149
|
-
definition,
|
|
150
|
-
field,
|
|
151
|
-
visible,
|
|
152
|
-
defaultValue,
|
|
153
|
-
scalarControl,
|
|
154
|
-
formState.readonly
|
|
155
|
-
);
|
|
156
|
-
},
|
|
157
|
-
useDisplayProperties: (fs, definition) => {
|
|
158
|
-
const visible = useIsControlVisible(definition, fs, useExpression);
|
|
159
|
-
return { visible };
|
|
160
|
-
},
|
|
161
|
-
useGroupProperties: (fs, definition, hooks) => {
|
|
162
|
-
const visible = useIsControlVisible(definition, fs, useExpression);
|
|
163
|
-
return { visible, hooks };
|
|
164
|
-
},
|
|
165
|
-
useActionProperties(
|
|
166
|
-
formState: FormEditState,
|
|
167
|
-
definition: ActionControlDefinition
|
|
168
|
-
): ActionControlProperties {
|
|
169
|
-
const visible = useIsControlVisible(definition, formState, useExpression);
|
|
170
|
-
return { visible, onClick: () => {} };
|
|
171
|
-
},
|
|
172
|
-
};
|
|
173
|
-
}
|