Skip to content

Commit b689df5

Browse files
Merge pull request #752 from gadget-inc/mill/removeTitleAndSubmitLabelFromFormWIthChildrenType
Updated AutoForm type to have a type error when given `title` or `submitLabel` when form has children
2 parents 6f402a7 + 189da21 commit b689df5

File tree

4 files changed

+36
-40
lines changed

4 files changed

+36
-40
lines changed

packages/react/src/auto/AutoForm.ts

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,30 @@ import {
2121
import { useFieldsFromChildComponents } from "./AutoFormContext.js";
2222
import { isAutoInput } from "./AutoInput.js";
2323

24+
/** When the AutoForm does not have children, these properties are available to control the rendering of the form */
25+
type AutoFormPropsWithoutChildren = {
26+
children?: never;
27+
28+
/** The title at the top of the form. False to omit */
29+
title?: string | false;
30+
31+
/** The label to use for the submit button at the bottom of the form */
32+
submitLabel?: ReactNode;
33+
};
34+
35+
type AutoFormPropsWithChildren = {
36+
/** Custom components to render within the form. Using this will override all default field rendering. */
37+
children?: ReactNode;
38+
};
39+
2440
/** The props that any <AutoForm/> component accepts */
2541
export type AutoFormProps<
2642
GivenOptions extends OptionsType,
2743
SchemaT,
2844
ActionFunc extends ActionFunction<GivenOptions, any, any, SchemaT, any> | GlobalActionFunction<any>,
2945
ExtraFormVariables extends FieldValues = Record<string, unknown>,
3046
DefaultValues = ActionFunc["variablesType"] & ExtraFormVariables
31-
> = {
47+
> = (AutoFormPropsWithChildren | AutoFormPropsWithoutChildren) & {
3248
/** Which action this fom will run on submit */
3349
action: ActionFunc;
3450
/** A record for this form to act on */
@@ -39,32 +55,26 @@ export type AutoFormProps<
3955
exclude?: string[];
4056
/** A set of field values to pre-populate the form with on load. Only applies to create forms. */
4157
defaultValues?: DefaultValues;
42-
/** The label to use for the submit button at the bottom of the form */
43-
submitLabel?: ReactNode;
4458
/** What to show the user once the form has been submitted successfully */
4559
successContent?: ReactNode;
46-
/** The title at the top of the form. False to omit */
47-
title?: string | false;
4860
/** Selection object to pass to the form to retrieve existing values. This will override the default selection based on included fields */
4961
select?: GivenOptions["select"];
5062
/** Called when the form submission completes successfully on the backend */
5163
onSuccess?: (record: UseActionFormHookStateData<ActionFunc>) => void;
5264
/** Called when the form submission errors before sending, during the API call, or if the API call returns an error. */
5365
onFailure?: (error: Error | FieldErrors<ActionFunc["variablesType"]>) => void;
54-
/** Custom components to render within the form. Using this will override all default field rendering. */
55-
children?: ReactNode;
5666
/** Enable debug logging for this form */
5767
debug?: boolean;
5868
} & (ActionFunc extends AnyActionWithId<GivenOptions>
59-
? {
60-
/**
61-
* The record identifier to run this action on, if it already exists.
62-
* Should be undefined for create actions, or a record ID (or finder) for update / etc actions
63-
**/
64-
findBy?: RecordIdentifier;
65-
}
66-
: // eslint-disable-next-line @typescript-eslint/ban-types
67-
{});
69+
? {
70+
/**
71+
* The record identifier to run this action on, if it already exists.
72+
* Should be undefined for create actions, or a record ID (or finder) for update / etc actions
73+
**/
74+
findBy?: RecordIdentifier;
75+
}
76+
: // eslint-disable-next-line @typescript-eslint/ban-types
77+
{});
6878

6979
/**
7080
* React hook for getting the validation schema for a list of fields
@@ -218,7 +228,9 @@ export const useAutoForm = <
218228

219229
const { hasCustomFormChildren, fieldSet, registerFields } = useFieldsFromChildComponents();
220230
const hasRegisteredFieldsFromChildren = hasCustomFormChildren && fieldSet.size > 0;
221-
const registeredFieldsFromChildren = hasCustomFormChildren ? extractPathsFromChildren(props.children) : [];
231+
const registeredFieldsFromChildren = hasCustomFormChildren
232+
? extractPathsFromChildren("children" in props ? props.children : undefined)
233+
: [];
222234

223235
useEffect(() => {
224236
registerFields(registeredFieldsFromChildren);

packages/react/src/auto/AutoFormActionValidators.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const validateAutoFormProps = (props: Parameters<typeof useAutoForm>[0])
3636
throw new Error(InvalidActionErrorMessage);
3737
}
3838

39-
if (props.children) {
39+
if ("children" in props && props.children) {
4040
if (props.include) {
4141
throw new Error(`AutoForm components with children cannot use the include option`);
4242
}

packages/react/src/auto/polaris/PolarisAutoForm.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ const PolarisAutoFormComponent = <
7979
originalFormMethods,
8080
} = useAutoForm(props);
8181

82-
const formTitle = props.title === undefined ? humanizeCamelCase(action.operationName) : props.title;
82+
const formTitle = "title" in props && props.title !== undefined ? props.title : humanizeCamelCase(action.operationName);
8383

8484
if (props.successContent && isSubmitSuccessful) {
8585
return props.successContent;
@@ -124,7 +124,7 @@ const PolarisAutoFormComponent = <
124124
<PolarisAutoInput field={metadata.apiIdentifier} key={metadata.apiIdentifier} />
125125
))}
126126
<div>
127-
<PolarisAutoSubmit>{props.submitLabel ?? "Submit"} </PolarisAutoSubmit>
127+
<PolarisAutoSubmit>{"submitLabel" in props && props.submitLabel ? props.submitLabel : "Submit"} </PolarisAutoSubmit>
128128
</div>
129129
</>
130130
)}

packages/react/src/auto/shadcn/ShadcnAutoForm.tsx

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,6 @@ export const makeAutoForm = <Elements extends ShadcnElements>({
9898
<AutoFormInner
9999
key={componentKey}
100100
{...(props as AutoFormProps<GivenOptions, SchemaT, ActionFunc> & Omit<Partial<FormProps>, "action"> & { findBy: any })}
101-
elements={{
102-
Form,
103-
Input,
104-
Button,
105-
Alert,
106-
Skeleton,
107-
AlertTitle,
108-
AlertDescription,
109-
ShadcnAutoInput: AutoInput,
110-
ShadcnAutoSubmit: AutoSubmit,
111-
}}
112101
/>
113102
</AutoFormFieldsFromChildComponentsProvider>
114103
);
@@ -118,18 +107,13 @@ export const makeAutoForm = <Elements extends ShadcnElements>({
118107
GivenOptions extends OptionsType,
119108
SchemaT,
120109
ActionFunc extends ActionFunction<GivenOptions, any, any, SchemaT, any>
121-
>(
122-
props: AutoFormProps<GivenOptions, SchemaT, ActionFunc> & {
123-
elements: ShadcnElements;
124-
} & ComponentProps<any>
125-
) {
110+
>(props: AutoFormProps<GivenOptions, SchemaT, ActionFunc> & ComponentProps<typeof Form>) {
126111
const {
127112
record: _record,
128113
action,
129114
findBy,
130115
...rest
131116
} = props as AutoFormProps<GivenOptions, SchemaT, ActionFunc> & Omit<Partial<FormProps>, "action"> & { findBy: any };
132-
const { Form, Skeleton, ShadcnAutoInput, ShadcnAutoSubmit } = props.elements;
133117

134118
const {
135119
metadata,
@@ -144,7 +128,7 @@ export const makeAutoForm = <Elements extends ShadcnElements>({
144128
isLoading,
145129
} = useAutoForm(props);
146130

147-
const formTitle = props.title === undefined ? humanizeCamelCase(action.operationName) : props.title;
131+
const formTitle = "title" in props && props.title !== undefined ? props.title : humanizeCamelCase(action.operationName);
148132

149133
if (props.successContent && isSubmitSuccessful) {
150134
return props.successContent;
@@ -182,9 +166,9 @@ export const makeAutoForm = <Elements extends ShadcnElements>({
182166
{!metadataError && (
183167
<>
184168
{fields.map(({ metadata }) => (
185-
<ShadcnAutoInput field={metadata.apiIdentifier} key={metadata.apiIdentifier} />
169+
<AutoInput field={metadata.apiIdentifier} key={metadata.apiIdentifier} />
186170
))}
187-
<ShadcnAutoSubmit>{props.submitLabel ?? "Submit"}</ShadcnAutoSubmit>
171+
<AutoSubmit>{"submitLabel" in props && props.submitLabel ? props.submitLabel : "Submit"}</AutoSubmit>
188172
</>
189173
)}
190174
</>

0 commit comments

Comments
 (0)