Skip to content

Commit 629f528

Browse files
authored
fix(autoform): showIf does not work if custom component is specified (react-page#1189)
fixes react-page#1187 the solution works around the problem, that if you set `props.component` any custom componentDetector is bypassed. also fixes a type error where the props that are passed to showIf had the wrong type. showIf always receives the base object.
1 parent ed7d2b8 commit 629f528

File tree

4 files changed

+125
-53
lines changed

4 files changed

+125
-53
lines changed

examples/plugins/customContentPlugin.tsx

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,45 @@ import type { CellPlugin } from '@react-page/editor';
22
import { ColorPickerField } from '@react-page/editor';
33
import React from 'react';
44

5+
type Palette = {
6+
variant: 'default' | 'highlight' | 'custom';
7+
customTextColor: string;
8+
customBackgroundColor: string;
9+
};
10+
11+
const getTextColor = (palette: Palette) => {
12+
if (palette?.variant === 'custom') {
13+
return palette.customTextColor;
14+
}
15+
if (palette?.variant === 'highlight') {
16+
return 'white';
17+
}
18+
return 'black';
19+
};
20+
const getBackgroundColor = (palette: Palette) => {
21+
if (palette?.variant === 'custom') {
22+
return palette.customBackgroundColor;
23+
}
24+
if (palette?.variant === 'highlight') {
25+
return '#3f51b5';
26+
}
27+
return 'white';
28+
};
529
const customContentPlugin: CellPlugin<{
630
title: string;
731
firstName: string;
832
lastName: string;
933
age: number;
1034
style: {
11-
backgroundColor: string;
12-
textColor: string;
35+
pallete: Palette;
1336
padding: number;
1437
};
1538
}> = {
1639
Renderer: ({ data }) => (
1740
<div
1841
style={{
19-
backgroundColor: data.style?.backgroundColor,
20-
color: data?.style?.textColor,
42+
backgroundColor: getBackgroundColor(data?.style?.pallete),
43+
color: getTextColor(data?.style?.pallete),
2144
padding: data?.style?.padding,
2245
}}
2346
>
@@ -66,19 +89,33 @@ const customContentPlugin: CellPlugin<{
6689
style: {
6790
type: 'object',
6891
required: [],
92+
6993
properties: {
70-
backgroundColor: {
71-
type: 'string',
72-
default: 'white',
73-
uniforms: {
74-
component: ColorPickerField,
75-
},
76-
},
77-
textColor: {
78-
type: 'string',
79-
default: 'black',
80-
uniforms: {
81-
component: ColorPickerField,
94+
pallete: {
95+
type: 'object',
96+
properties: {
97+
variant: {
98+
type: 'string',
99+
enum: ['default', 'highlight', 'custom'],
100+
},
101+
customBackgroundColor: {
102+
type: 'string',
103+
default: 'white',
104+
uniforms: {
105+
component: ColorPickerField,
106+
showIf: (data) =>
107+
data.style?.pallete?.variant === 'custom',
108+
},
109+
},
110+
customTextColor: {
111+
type: 'string',
112+
default: 'black',
113+
uniforms: {
114+
component: ColorPickerField,
115+
showIf: (data) =>
116+
data.style?.pallete?.variant === 'custom',
117+
},
118+
},
82119
},
83120
},
84121

packages/editor/src/core/types/jsonSchema.ts

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,41 @@
11
import type React from 'react';
22
import type { DataTType } from '.';
33

4-
type UniformsProps<Data> = Record<string, unknown> & {
4+
type UniformsProps<FullData> = Record<string, unknown> & {
55
label?: string;
66
placeholder?: string;
77
multiline?: boolean;
88
component?: React.ComponentType<{ name: string }>;
99
/**
1010
* whether to show the field
1111
*/
12-
showIf?: (data: Data) => boolean;
12+
showIf?: (data: FullData) => boolean;
1313
};
14-
type CommonPropertyProps<Data> = {
14+
15+
type WithEnum<FieldT> = {
16+
/**
17+
* If you want to show a list of possible values, specify the enum prop.
18+
* The values will be shown in a select field
19+
*/
20+
enum?: FieldT[];
21+
};
22+
type CommonPropertyProps<FullData> = {
1523
/**
1624
* title to display
1725
*/
1826
title?: string;
1927
/**
2028
* uniforms properties, passed to the form field
2129
*/
22-
uniforms?: UniformsProps<Data>;
30+
uniforms?: UniformsProps<FullData>;
31+
2332
/**
2433
* additionl props
2534
*/
2635
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2736
[key: string]: any;
2837
};
29-
type BooleanType<Data> = {
38+
type BooleanType<FullData> = {
3039
/**
3140
* boolean type is for checkboxes
3241
*/
@@ -35,9 +44,9 @@ type BooleanType<Data> = {
3544
* default value
3645
*/
3746
default?: boolean;
38-
} & CommonPropertyProps<Data>;
47+
} & CommonPropertyProps<FullData>;
3948

40-
type StringProperty<Data> = {
49+
type StringProperty<FullData> = {
4150
/**
4251
* string type is for strings and render an input field
4352
*/
@@ -58,9 +67,10 @@ type StringProperty<Data> = {
5867
* regex pattern to validate, e.g. for email adresses
5968
*/
6069
pattern?: string;
61-
} & CommonPropertyProps<Data>;
70+
} & CommonPropertyProps<FullData> &
71+
WithEnum<string>;
6272

63-
type NumberProperty<Data> = {
73+
type NumberProperty<FullData> = {
6474
/**
6575
* type number is for float numbers, integer is for integers only
6676
*/
@@ -85,10 +95,37 @@ type NumberProperty<Data> = {
8595
* maximum but value has to be strictly smaller than this maximum
8696
*/
8797
exclusiveMaximum?: boolean;
88-
} & CommonPropertyProps<Data>;
98+
} & CommonPropertyProps<FullData> &
99+
WithEnum<number>;
89100

90-
type ObjectProperty<T extends Record<string, unknown>, Data> = JsonSchema<T> &
91-
CommonPropertyProps<Data>;
101+
type BaseObjectProps<FieldData extends Record<string, unknown>, FullData> = {
102+
title?: string;
103+
/**
104+
* type object is for a nested object
105+
*/
106+
type?: 'object';
107+
/**
108+
* the default value
109+
*/
110+
default?: FieldData;
111+
/**
112+
* child properties of this object
113+
*/
114+
properties: {
115+
[Field in keyof FieldData]?: JsonSchemaProperty<FieldData[Field], FullData>;
116+
};
117+
// required: string[];
118+
/* union to tuple conversion is expensive, we do a poor mans version here */
119+
/**
120+
* required fields
121+
*/
122+
required?: Array<keyof FieldData>;
123+
};
124+
125+
type ObjectProperty<
126+
FieldData extends Record<string, unknown>,
127+
FullData
128+
> = BaseObjectProps<FieldData, FullData> & CommonPropertyProps<FullData>;
92129
type ArrayProperty<Field, Data> = {
93130
/**
94131
* array type is for array objects
@@ -111,24 +148,4 @@ export type JsonSchemaProperty<Field, Data> = Field extends (infer U)[]
111148
? BooleanType<Data>
112149
: never;
113150

114-
export type JsonSchema<Data extends DataTType> = {
115-
title?: string;
116-
/**
117-
* type object is for a nested object
118-
*/
119-
type?: 'object';
120-
/**
121-
* the default value
122-
*/
123-
default?: Data;
124-
/**
125-
* child properties of this object
126-
*/
127-
properties: { [Field in keyof Data]?: JsonSchemaProperty<Data[Field], Data> };
128-
// required: string[];
129-
/* union to tuple conversion is expensive, we do a poor mans version here */
130-
/**
131-
* required fields
132-
*/
133-
required?: Array<keyof Data>;
134-
};
151+
export type JsonSchema<Data extends DataTType> = BaseObjectProps<Data, Data>;

packages/editor/src/ui/AutoformControls/AutoFieldContext.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ const AutofieldContextProvider: React.FC = ({ children }) => (
55
<AutoField.componentDetectorContext.Provider
66
value={(props, uniforms) => {
77
const show = props.showIf?.(uniforms.model) ?? true;
8+
if (!show) return () => null;
89

9-
return show
10-
? AutoField.defaultComponentDetector(props, uniforms)
11-
: () => null;
10+
// see https://github.com/react-page/react-page/issues/1187
11+
// we remap props.component to props._customComponent to avoid the underlying issue in uniforms
12+
if (props._customComponent) {
13+
return props._customComponent;
14+
}
15+
return AutoField.defaultComponentDetector(props, uniforms);
1216
}}
1317
>
1418
{children}

packages/editor/src/ui/AutoformControls/makeUniformsSchema.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,21 @@ function makeUniformsSchema<T extends DataTType>(
2525
type: 'object',
2626
...jsonSchema,
2727
};
28-
return new JSONSchemaBridge(fullSchema, createValidator(fullSchema));
28+
const bridge = new JSONSchemaBridge(fullSchema, createValidator(fullSchema));
29+
30+
// see https://github.com/react-page/react-page/issues/1187
31+
// we remap props.component to props._customComponent to avoid the underlying issue in uniforms
32+
//
33+
const getPropsOrg = bridge.getProps;
34+
bridge.getProps = function (name: string) {
35+
const { component, ...props } = getPropsOrg.call(this, name);
36+
37+
return {
38+
_customComponent: component,
39+
...props,
40+
};
41+
};
42+
return bridge;
2943
}
3044

3145
export default makeUniformsSchema;

0 commit comments

Comments
 (0)