Skip to content

Commit

Permalink
feat: add input component as types, simplify event handlers - emailpa…
Browse files Browse the repository at this point in the history
…ssword recipe (#752)

* Add inputComponent to exposed types

* Add inputComponent to normalised fields

* For testing only - use custom type definition for inputComponent

* Input component already present in  FormFieldThemeProps

* Testing if git package is getting installed correctly

* Run build for previous commits

* Remove inputComp from NormalizedFormField

* Add tests for custom fields

* Remove testing ele

* Move the custom fields tests into existing describe

* Update dropdown values to avoid confusion

* Add helper func to set dropdown, better test title, use existing describe hooks

* Use strict equal

* Update request

* A seperate func to fetch custom comp not required

* Move inputComponent to signup types

* Cleanup unwanted imports

* Move inputComponent to signup types

* Clean types

* Update build files

* Use explicit values in validate func

* Minor cleanup of types

* Better type names

* Props suggestions working for inputComponent

* Enforce strict string check on form values, now onChange function for fields only needs value, no need to supply name or id

* Update based on the new onChange func

* Ability to add default value with getDefaultValue prop

* Handle if getDefaultValue is not a function

* instead of form submit apply type test within onChange function itself

* Add tests for default value

* Remove unwanted abort

* Testing email-verification workflow

* Reverting onChange changes

* onChange function to accept only values

* Initialize fieldstates at the start

* Remove useEffect

* Fix race conditions when setting default value

* Add custom default fields to typescript example, plus add tests to show custom error message

* Add tests for incorrect default props in formFields

* Add tests for incorrect usage of onChange prop

* Add change log

* Wrap ternary opeators into seperate func for better readibility

* Wrap inputComponent in a serperate component to avoid unecessary rerenders

* Add change log feedbacks

* Better variable names, include formfields directly in typescript example

* Add more tests for default & onChange func, updated typescript file to show the latest changes

* Add more test, which intercepts request payload

* Cleanup comments

* Minor formatting

* Minor fix

* Clean up helper

* Update change log & versions
  • Loading branch information
amitbadala authored Nov 3, 2023
1 parent 78dc12e commit 2127c64
Show file tree
Hide file tree
Showing 23 changed files with 864 additions and 667 deletions.
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,46 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)

## [0.36.0] - 2023-10-30

### Added

- Introduced the capability to utilize custom components in the Email-Password based recipes' signup form fields by exposing inputComponent types.
- Implemented the functionality to assign default values to the form fields in the Email-Password based recipes.
- Simplified onChange prop usage in inputComponent - id attribute removed.

Following is an example of how to use above features.

```tsx
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "select-dropdown",
label: "Select Option",
getDefaultValue: () => "option 2",
inputComponent: ({ value, name, onChange }) => (
<select
value={value}
name={name}
onChange={(e) => onChange(e.target.value)}
placeholder="Select Option">
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
},
],
},
},
});
```

## [0.35.6] - 2023-10-16

### Test changes
Expand Down
171 changes: 170 additions & 1 deletion examples/for-tests/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,159 @@ const formFields = [
},
];

const formFieldsWithDefault = [
{
id: "country",
label: "Your Country",
placeholder: "Where do you live?",
optional: true,
getDefaultValue: () => "India",
},
{
id: "select-dropdown",
label: "Select Option",
getDefaultValue: () => "option 2",
inputComponent: ({ value, name, onChange }) => (
<select value={value} name={name} onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
optional: true,
},
{
id: "terms",
label: "",
optional: false,
getDefaultValue: () => "true",
inputComponent: ({ name, onChange, value }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input
value={value}
checked={value === "true"}
name={name}
type="checkbox"
onChange={(e) => onChange(e.target.checked.toString())}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
validate: async (value) => {
if (value === "true") {
return undefined;
}
return "Please check Terms and conditions";
},
},
{
id: "email",
label: "Email",
getDefaultValue: () => "[email protected]",
},
{
id: "password",
label: "Password",
getDefaultValue: () => "fakepassword123",
},
];

const incorrectFormFields = [
{
id: "country",
label: "Your Country",
placeholder: "Where do you live?",
optional: true,
getDefaultValue: () => 23, // return should be a string
},
{
id: "select-dropdown",
label: "Select Dropdown",
getDefaultValue: "option 2", // should be function
inputComponent: ({ value, name, onChange }) => (
<select value={value} name={name} onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
optional: true,
},
{
// onChange accepts only string value, here we pass boolean
id: "terms",
label: "",
optional: false,
inputComponent: ({ name, onChange }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input name={name} type="checkbox" onChange={(e) => onChange(e.target.checked)}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
validate: async (value) => {
if (value === "true") {
return undefined;
}
return "Please check Terms and conditions";
},
},
];

const customFields = [
{
id: "select-dropdown",
label: "Select Dropdown",
inputComponent: ({ value, name, onChange }) => (
<select value={value} name={name} onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
optional: true,
},
{
id: "terms",
label: "",
optional: false,
inputComponent: ({ name, onChange }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input name={name} type="checkbox" onChange={(e) => onChange(e.target.checked.toString())}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
validate: async (value) => {
if (value === "true") {
return undefined;
}
return "Please check Terms and conditions";
},
},
];

const testContext = getTestContext();

let recipeList = [
Expand Down Expand Up @@ -552,6 +705,22 @@ function getEmailVerificationConfigs({ disableDefaultUI }) {
});
}

function getFormFields() {
if (localStorage.getItem("SHOW_INCORRECT_FIELDS") === "YES") {
if (localStorage.getItem("INCORRECT_ONCHANGE") === "YES") {
// since page-error blocks all the other errors
// use this filter to test specific error
return incorrectFormFields.filter(({ id }) => id === "terms");
}
return incorrectFormFields;
} else if (localStorage.getItem("SHOW_CUSTOM_FIELDS_WITH_DEFAULT_VALUES") === "YES") {
return formFieldsWithDefault;
} else if (localStorage.getItem("SHOW_CUSTOM_FIELDS") === "YES") {
return customFields;
}
return formFields;
}

function getEmailPasswordConfigs({ disableDefaultUI }) {
return EmailPassword.init({
style: `
Expand Down Expand Up @@ -637,7 +806,7 @@ function getEmailPasswordConfigs({ disableDefaultUI }) {
style: theme,
privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
formFields,
formFields: getFormFields(),
},
},
});
Expand Down
Loading

0 comments on commit 2127c64

Please sign in to comment.