@@ -55,6 +55,10 @@ const DEFAULT_COPY = {
5555 * Error message when the passwords do not match.
5656 */
5757 error_password_mismatch : "Passwords do not match." ,
58+ /**
59+ * Error message when the user enters a password that fails validation.
60+ */
61+ error_validation_error : "Password does not meet requirements." ,
5862 /**
5963 * Title of the register page.
6064 */
@@ -136,18 +140,8 @@ type PasswordUICopy = typeof DEFAULT_COPY
136140/**
137141 * Configure the password UI.
138142 */
139- export interface PasswordUIOptions {
140- /**
141- * Callback to send the confirmation code to the user.
142- *
143- * @example
144- * ```ts
145- * async (email, code) => {
146- * // Send an email with the code
147- * }
148- * ```
149- */
150- sendCode : PasswordConfig [ "sendCode" ]
143+ export interface PasswordUIOptions
144+ extends Pick < PasswordConfig , "sendCode" | "validatePassword" > {
151145 /**
152146 * Custom copy for the UI.
153147 */
@@ -164,6 +158,7 @@ export function PasswordUI(input: PasswordUIOptions): PasswordConfig {
164158 ...input . copy ,
165159 }
166160 return {
161+ validatePassword : input . validatePassword ,
167162 sendCode : input . sendCode ,
168163 login : async ( _req , form , error ) : Promise < Response > => {
169164 const jsx = (
@@ -214,13 +209,23 @@ export function PasswordUI(input: PasswordUIOptions): PasswordConfig {
214209 const emailError = [ "invalid_email" , "email_taken" ] . includes (
215210 error ?. type || "" ,
216211 )
217- const passwordError = [ "invalid_password" , "password_mismatch" ] . includes (
218- error ?. type || "" ,
219- )
212+ const passwordError = [
213+ "invalid_password" ,
214+ "password_mismatch" ,
215+ "validation_error" ,
216+ ] . includes ( error ?. type || "" )
220217 const jsx = (
221218 < Layout >
222219 < form data-component = "form" method = "post" >
223- < FormAlert message = { error ?. type && copy ?. [ `error_${ error . type } ` ] } />
220+ < FormAlert
221+ message = {
222+ error ?. type
223+ ? error . type === "validation_error"
224+ ? ( error . message ?? copy ?. [ `error_${ error . type } ` ] )
225+ : copy ?. [ `error_${ error . type } ` ]
226+ : undefined
227+ }
228+ />
224229 { state . type === "start" && (
225230 < >
226231 < input type = "hidden" name = "action" value = "register" />
@@ -292,13 +297,23 @@ export function PasswordUI(input: PasswordUIOptions): PasswordConfig {
292297 } )
293298 } ,
294299 change : async ( _req , state , form , error ) : Promise < Response > => {
295- const passwordError = [ "invalid_password" , "password_mismatch" ] . includes (
296- error ?. type || "" ,
297- )
300+ const passwordError = [
301+ "invalid_password" ,
302+ "password_mismatch" ,
303+ "validation_error" ,
304+ ] . includes ( error ?. type || "" )
298305 const jsx = (
299306 < Layout >
300307 < form data-component = "form" method = "post" replace >
301- < FormAlert message = { error ?. type && copy ?. [ `error_${ error . type } ` ] } />
308+ < FormAlert
309+ message = {
310+ error ?. type
311+ ? error . type === "validation_error"
312+ ? ( error . message ?? copy ?. [ `error_${ error . type } ` ] )
313+ : copy ?. [ `error_${ error . type } ` ]
314+ : undefined
315+ }
316+ />
302317 { state . type === "start" && (
303318 < >
304319 < input type = "hidden" name = "action" value = "code" />
0 commit comments