@react-typed-forms/schemas 7.0.0 → 7.2.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.
@@ -41,7 +41,7 @@ export declare function stringOptionsField(displayName: string, ...options: Fiel
41
41
  displayName: string;
42
42
  options: FieldOption[];
43
43
  };
44
- export declare function withScalarOptions<S extends SchemaField>(options: Partial<SchemaField>, v: (name: string) => S): (name: string) => S;
44
+ export declare function withScalarOptions<S extends SchemaField, S2 extends Partial<SchemaField>>(options: S2, v: (name: string) => S): (name: string) => S & S2;
45
45
  export declare function makeScalarField<S extends Partial<SchemaField>>(options: S): (name: string) => SchemaField & S;
46
46
  export declare function makeCompoundField<S extends Partial<CompoundField>>(options: S): (name: string) => CompoundField & {
47
47
  type: FieldType.Compound;
package/lib/types.d.ts CHANGED
@@ -72,7 +72,8 @@ export declare enum DynamicPropertyType {
72
72
  Disabled = "Disabled",
73
73
  Display = "Display",
74
74
  Style = "Style",
75
- LayoutStyle = "LayoutStyle"
75
+ LayoutStyle = "LayoutStyle",
76
+ AllowedOptions = "AllowedOptions"
76
77
  }
77
78
  export interface EntityExpression {
78
79
  type: string;
package/lib/util.d.ts CHANGED
@@ -3,6 +3,7 @@ import { MutableRefObject } from "react";
3
3
  import { Control } from "@react-typed-forms/core";
4
4
  export interface ControlDataContext {
5
5
  groupControl: Control<any>;
6
+ root: Control<any>;
6
7
  fields: SchemaField[];
7
8
  schemaInterface: SchemaInterface;
8
9
  }
package/package.json CHANGED
@@ -1,49 +1,49 @@
1
1
  {
2
- "name": "@react-typed-forms/schemas",
3
- "version": "7.0.0",
4
- "description": "",
5
- "main": "lib/index.js",
6
- "types": "lib/index.d.ts",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/doolse/react-typed-forms.git"
10
- },
11
- "author": "Jolse Maginnis",
12
- "license": "ISC",
13
- "bugs": {
14
- "url": "https://github.com/doolse/react-typed-forms/issues"
15
- },
16
- "homepage": "https://github.com/doolse/react-typed-forms#readme",
17
- "publishConfig": {
18
- "access": "public"
19
- },
20
- "keywords": [
21
- "react",
22
- "typescript",
23
- "forms",
24
- "material-ui"
25
- ],
26
- "dependencies": {
27
- "@react-typed-forms/core": "^3.0.0",
28
- "clsx": "^1 || ^2",
29
- "jsonata": "^2.0.4",
30
- "react": "^18.2.0"
31
- },
32
- "devDependencies": {
33
- "@react-typed-forms/transform": "^0.2.0",
34
- "@types/react": "^18.2.28",
35
- "markdown-magic": "^2.6.1",
36
- "microbundle": "^0.15.1",
37
- "nswag": "^13.18.2",
38
- "prettier": "^3.0.3",
39
- "rimraf": "^3.0.2",
40
- "typescript": "^5.2.2"
41
- },
42
- "gitHead": "698e16cd3ab31b7dd0528fc76536f4d3205ce8c6",
43
- "scripts": {
44
- "build": "rimraf ./lib/ && microbundle -f cjs --no-compress --jsx React.createElement --jsxFragment React.Fragment",
45
- "watch": "microbundle -w -f cjs --no-compress --jsx React.createElement --jsxFragment React.Fragment",
46
- "update-readme": "md-magic --path README.md",
47
- "gencode": "nswag swagger2tsclient /input:http://localhost:5216/swagger/v1/swagger.json /runtime:Net60 /output:src/types.ts /GenerateClientClasses:false /MarkOptionalProperties:false /Template:Fetch /TypeStyle:Interface /DateTimeType:string"
48
- }
49
- }
2
+ "name": "@react-typed-forms/schemas",
3
+ "version": "7.2.0",
4
+ "description": "",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/doolse/react-typed-forms.git"
10
+ },
11
+ "author": "Jolse Maginnis",
12
+ "license": "ISC",
13
+ "bugs": {
14
+ "url": "https://github.com/doolse/react-typed-forms/issues"
15
+ },
16
+ "homepage": "https://github.com/doolse/react-typed-forms#readme",
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "keywords": [
21
+ "react",
22
+ "typescript",
23
+ "forms",
24
+ "material-ui"
25
+ ],
26
+ "dependencies": {
27
+ "@react-typed-forms/core": "^3.0.0",
28
+ "clsx": "^1 || ^2",
29
+ "jsonata": "^2.0.4",
30
+ "react": "^18.2.0"
31
+ },
32
+ "devDependencies": {
33
+ "@react-typed-forms/transform": "^0.2.0",
34
+ "@types/react": "^18.2.28",
35
+ "markdown-magic": "^2.6.1",
36
+ "microbundle": "^0.15.1",
37
+ "nswag": "^13.18.2",
38
+ "prettier": "^3.0.3",
39
+ "rimraf": "^3.0.2",
40
+ "typescript": "^5.2.2"
41
+ },
42
+ "gitHead": "698e16cd3ab31b7dd0528fc76536f4d3205ce8c6",
43
+ "scripts": {
44
+ "build": "rimraf ./lib/ && microbundle -f cjs --no-compress --jsx React.createElement --jsxFragment React.Fragment",
45
+ "watch": "microbundle -w -f cjs --no-compress --jsx React.createElement --jsxFragment React.Fragment",
46
+ "update-readme": "md-magic --path README.md",
47
+ "gencode": "nswag swagger2tsclient /input:http://localhost:5216/swagger/v1/swagger.json /runtime:Net60 /output:src/types.ts /GenerateClientClasses:false /MarkOptionalProperties:false /Template:Fetch /TypeStyle:Interface /DateTimeType:string"
48
+ }
49
+ }
@@ -44,6 +44,7 @@ import {
44
44
  import { dataControl } from "./controlBuilder";
45
45
  import {
46
46
  defaultUseEvalExpressionHook,
47
+ useEvalAllowedOptionsHook,
47
48
  useEvalDefaultValueHook,
48
49
  useEvalDisabledHook,
49
50
  useEvalDisplayHook,
@@ -208,6 +209,7 @@ export interface DataControlProps {
208
209
  style: React.CSSProperties | undefined;
209
210
  childCount: number;
210
211
  renderChild: ChildRenderer;
212
+ allowedOptions?: Control<any[] | undefined>;
211
213
  elementRenderer?: (elemProps: Control<any>) => ReactNode;
212
214
  }
213
215
  export type CreateDataProps = (
@@ -219,6 +221,7 @@ export interface ControlRenderOptions extends FormContextOptions {
219
221
  useEvalExpressionHook?: UseEvalExpressionHook;
220
222
  clearHidden?: boolean;
221
223
  schemaInterface?: SchemaInterface;
224
+ dataRoot?: Control<any>;
222
225
  }
223
226
  export function useControlRenderer(
224
227
  definition: ControlDefinition,
@@ -239,6 +242,7 @@ export function useControlRenderer(
239
242
  const useIsVisible = useEvalVisibilityHook(useExpr, definition, schemaField);
240
243
  const useIsReadonly = useEvalReadonlyHook(useExpr, definition);
241
244
  const useIsDisabled = useEvalDisabledHook(useExpr, definition);
245
+ const useAllowedOptions = useEvalAllowedOptionsHook(useExpr, definition);
242
246
  const useCustomStyle = useEvalStyleHook(
243
247
  useExpr,
244
248
  DynamicPropertyType.Style,
@@ -262,6 +266,7 @@ export function useControlRenderer(
262
266
  groupControl: parentControl,
263
267
  fields,
264
268
  schemaInterface,
269
+ root: options.dataRoot ?? parentControl,
265
270
  };
266
271
  const readonlyControl = useIsReadonly(dataContext);
267
272
  const disabledControl = useIsDisabled(dataContext);
@@ -289,6 +294,7 @@ export function useControlRenderer(
289
294
  },
290
295
  );
291
296
 
297
+ const allowedOptions = useAllowedOptions(dataContext);
292
298
  const defaultValueControl = useDefaultValue(dataContext);
293
299
  const [control, childContext] = getControlData(
294
300
  schemaField,
@@ -327,6 +333,7 @@ export function useControlRenderer(
327
333
  useControlRenderer(cd, childContext.fields, renderer, {
328
334
  ...options,
329
335
  ...myOptions,
336
+ dataRoot: dataContext.root,
330
337
  }),
331
338
  ) ?? [];
332
339
  useEffect(() => {
@@ -353,6 +360,7 @@ export function useControlRenderer(
353
360
  schemaField,
354
361
  displayControl,
355
362
  style: customStyle,
363
+ allowedOptions,
356
364
  });
357
365
  const renderedControl = renderer.renderLayout({
358
366
  ...labelAndChildren,
@@ -374,6 +382,7 @@ export function useControlRenderer(
374
382
  useIsDisabled,
375
383
  useCustomStyle,
376
384
  useLayoutStyle,
385
+ useAllowedOptions,
377
386
  useDynamicDisplay,
378
387
  useValidation,
379
388
  renderer,
@@ -390,8 +399,8 @@ export function lookupSchemaField(
390
399
  const fieldName = isGroupControlsDefinition(c)
391
400
  ? c.compoundField
392
401
  : isDataControlDefinition(c)
393
- ? c.field
394
- : undefined;
402
+ ? c.field
403
+ : undefined;
395
404
  return fieldName ? findField(fields, fieldName) : undefined;
396
405
  }
397
406
  export function getControlData(
@@ -405,9 +414,9 @@ export function getControlData(
405
414
  childControl,
406
415
  schemaField && isCompoundField(schemaField)
407
416
  ? {
417
+ ...parentContext,
408
418
  groupControl: childControl!,
409
419
  fields: schemaField.children,
410
- schemaInterface: parentContext.schemaInterface,
411
420
  }
412
421
  : parentContext,
413
422
  ];
@@ -437,15 +446,22 @@ export function defaultDataProps({
437
446
  options,
438
447
  elementRenderer,
439
448
  style,
449
+ allowedOptions,
440
450
  ...props
441
451
  }: DataControlProps): DataRendererProps {
442
452
  const className = cc(definition.styleClass);
443
453
  const required = !!definition.required;
454
+ const fieldOptions =
455
+ (field.options?.length ?? 0) === 0 ? null : field.options;
456
+ const allowed = allowedOptions?.value ?? [];
444
457
  return {
445
458
  control,
446
459
  field,
447
460
  id: "c" + control.uniqueId,
448
- options: (field.options?.length ?? 0) === 0 ? null : field.options,
461
+ options:
462
+ fieldOptions && allowed.length > 0
463
+ ? fieldOptions.filter((x) => allowed.includes(x.value))
464
+ : fieldOptions,
449
465
  readonly: !!options.readonly,
450
466
  renderOptions: definition.renderOptions ?? { type: "Standard" },
451
467
  required,
@@ -516,6 +532,7 @@ export interface RenderControlProps {
516
532
  schemaField?: SchemaField;
517
533
  displayControl?: Control<string | undefined>;
518
534
  style?: React.CSSProperties;
535
+ allowedOptions?: Control<any[] | undefined>;
519
536
  }
520
537
  export function renderControlLayout({
521
538
  definition: c,
@@ -529,6 +546,7 @@ export function renderControlLayout({
529
546
  createDataProps: dataProps,
530
547
  displayControl,
531
548
  style,
549
+ allowedOptions,
532
550
  }: RenderControlProps): ControlLayoutProps {
533
551
  if (isDataControlDefinition(c)) {
534
552
  return renderData(c);
@@ -593,6 +611,7 @@ export function renderControlLayout({
593
611
  options: dataOptions,
594
612
  style,
595
613
  childCount,
614
+ allowedOptions,
596
615
  renderChild: childRenderer,
597
616
  elementRenderer:
598
617
  elementControl == null && schemaField.collection
package/src/hooks.tsx CHANGED
@@ -105,6 +105,24 @@ export function useEvalStyleHook(
105
105
  );
106
106
  }
107
107
 
108
+ export function useEvalAllowedOptionsHook(
109
+ useEvalExpressionHook: UseEvalExpressionHook,
110
+ definition: ControlDefinition,
111
+ ): EvalExpressionHook<any[]> {
112
+ const dynamicAllowed = useEvalDynamicHook(
113
+ definition,
114
+ DynamicPropertyType.AllowedOptions,
115
+ useEvalExpressionHook,
116
+ );
117
+ return useCallback(
118
+ (ctx) => {
119
+ if (dynamicAllowed) return dynamicAllowed(ctx);
120
+ return useControl([]);
121
+ },
122
+ [dynamicAllowed],
123
+ );
124
+ }
125
+
108
126
  export function useEvalDisabledHook(
109
127
  useEvalExpressionHook: UseEvalExpressionHook,
110
128
  definition: ControlDefinition,
@@ -203,6 +221,7 @@ export function defaultEvalHooks(
203
221
  return useJsonataExpression(
204
222
  (expr as JsonataExpression).expression,
205
223
  context.groupControl,
224
+ context.root,
206
225
  );
207
226
  case ExpressionType.Data:
208
227
  return useDataExpression(
@@ -280,20 +299,21 @@ export function hideDisplayOnly(
280
299
  export function useJsonataExpression(
281
300
  jExpr: string,
282
301
  data: Control<any>,
302
+ root: Control<any>,
283
303
  ): Control<any> {
284
304
  const compiledExpr = useMemo(() => {
285
305
  try {
286
306
  return jsonata(jExpr);
287
307
  } catch (e) {
288
308
  console.error(e);
289
- return jsonata("");
309
+ return jsonata("null");
290
310
  }
291
311
  }, [jExpr]);
292
312
  const control = useControl();
293
313
  useControlEffect(
294
- () => data.value,
295
- async (v) => {
296
- control.value = await compiledExpr.evaluate(v);
314
+ () => [data.value, root.value],
315
+ async ([v, rv]) => {
316
+ control.value = await compiledExpr.evaluate(v, { root: rv });
297
317
  },
298
318
  true,
299
319
  );
@@ -5,22 +5,22 @@ type AllowedSchema<T> = T extends string
5
5
  type: FieldType.String | FieldType.Date | FieldType.DateTime;
6
6
  }
7
7
  : T extends number
8
- ? SchemaField & {
9
- type: FieldType.Int | FieldType.Double;
10
- }
11
- : T extends boolean
12
- ? SchemaField & {
13
- type: FieldType.Bool;
14
- }
15
- : T extends Array<infer E>
16
- ? AllowedSchema<E> & {
17
- collection: true;
18
- }
19
- : T extends { [key: string]: any }
20
- ? CompoundField & {
21
- type: FieldType.Compound;
22
- }
23
- : SchemaField & { type: FieldType.Any };
8
+ ? SchemaField & {
9
+ type: FieldType.Int | FieldType.Double;
10
+ }
11
+ : T extends boolean
12
+ ? SchemaField & {
13
+ type: FieldType.Bool;
14
+ }
15
+ : T extends Array<infer E>
16
+ ? AllowedSchema<E> & {
17
+ collection: true;
18
+ }
19
+ : T extends { [key: string]: any }
20
+ ? CompoundField & {
21
+ type: FieldType.Compound;
22
+ }
23
+ : SchemaField & { type: FieldType.Any };
24
24
 
25
25
  type AllowedField<T, K> = (
26
26
  name: string,
@@ -56,10 +56,10 @@ export function stringOptionsField(
56
56
  });
57
57
  }
58
58
 
59
- export function withScalarOptions<S extends SchemaField>(
60
- options: Partial<SchemaField>,
61
- v: (name: string) => S,
62
- ): (name: string) => S {
59
+ export function withScalarOptions<
60
+ S extends SchemaField,
61
+ S2 extends Partial<SchemaField>,
62
+ >(options: S2, v: (name: string) => S): (name: string) => S & S2 {
63
63
  return (n) => ({ ...v(n), ...options });
64
64
  }
65
65
 
package/src/types.ts CHANGED
@@ -90,6 +90,7 @@ export enum DynamicPropertyType {
90
90
  Display = "Display",
91
91
  Style = "Style",
92
92
  LayoutStyle = "LayoutStyle",
93
+ AllowedOptions = "AllowedOptions"
93
94
  }
94
95
 
95
96
  export interface EntityExpression {
package/src/util.ts CHANGED
@@ -22,6 +22,7 @@ import clsx from "clsx";
22
22
 
23
23
  export interface ControlDataContext {
24
24
  groupControl: Control<any>;
25
+ root: Control<any>;
25
26
  fields: SchemaField[];
26
27
  schemaInterface: SchemaInterface;
27
28
  }
@@ -318,9 +319,9 @@ export function visitControlData<A>(
318
319
  const cfResult = visitControlDataArray(
319
320
  children,
320
321
  {
322
+ ...ctx,
321
323
  fields: fieldData.children,
322
324
  groupControl: c,
323
- schemaInterface: ctx.schemaInterface,
324
325
  },
325
326
  cb,
326
327
  );
package/src/validators.ts CHANGED
@@ -70,7 +70,11 @@ function useJsonataValidator(
70
70
  hidden: boolean,
71
71
  i: number,
72
72
  ) {
73
- const errorMsg = useJsonataExpression(expr.expression, context.groupControl);
73
+ const errorMsg = useJsonataExpression(
74
+ expr.expression,
75
+ context.groupControl,
76
+ context.root,
77
+ );
74
78
  useControlEffect(
75
79
  () => [hidden, errorMsg.value],
76
80
  ([hidden, msg]) => control.setError("jsonata" + i, !hidden ? msg : null),