Skip to content

Commit

Permalink
Proof of concept
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Bendel authored and Chris Bendel committed Sep 25, 2023
1 parent dd67a99 commit 0a16779
Showing 1 changed file with 45 additions and 12 deletions.
57 changes: 45 additions & 12 deletions src/form.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
import { FCWC, React, cx, PropsWithChildren, useEffect, useMemo } from './common.js'
import { cx, FCWC, isSSR, PropsWithChildren, React, useEffect, useMemo } from './common.js'
import type { ReactNode } from 'react'
import { useCallback } from 'react'
import type { AnyObjectSchema } from 'yup'
import { isShallowEqual, errorToString } from './util.js'
import { errorToString, isShallowEqual } from './util.js'
import { usePreviousValue, useToggle } from './hooks.js'
import {
useForm,
useWatch as useFormValue,
FieldError,
FormProvider,
SubmitHandler,
FieldError,
useForm,
useWatch as useFormValue,
} from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'
import { Box } from 'boxible'
import { Footer } from './footer.js'
import { FormStatusAlert } from './form-status-alert.js'
import { Button, ButtonProps } from './button.js'
import { ErrorTypes } from './types.js'
import { useCallback } from 'react'

import type { FieldState, FormContext, RegisteredField } from './form-hooks.js'
import {
FormTriggerValidation,
FORM_ERROR_KEY,
FormTriggerValidation,
useController,
useFormState,
useFormContext,
useFormState,
} from './form-hooks.js'
import type { FieldState, RegisteredField, FormContext } from './form-hooks.js'

export * from './form-hooks.js'
export * from './date-time-field.js'
export * from './date-time.js'
Expand All @@ -45,7 +46,9 @@ export type FormSubmitHandler<FV extends FormValues = object> = (
ctx: FormContext<FV>
) => void | Promise<void>
export type FormCancelHandler<FV extends FormValues = object> = (fc: FormContext<FV>) => void
export type FormDeleteHandler<FV extends FormValues = object> = (fc: FormContext<FV>) => Promise<void>
export type FormDeleteHandler<FV extends FormValues = object> = (
fc: FormContext<FV>
) => Promise<void>

export type FormValues = Record<string, any>

Expand All @@ -63,6 +66,7 @@ interface FormProps<FV extends FormValues> {
onReset?: (values: FV, ctx: FormContext<FV>) => void
onSubmit: FormSubmitHandler<FV>
validationSchema?: AnyObjectSchema
confirmOnNavigate: boolean
}

const KEEP_STATE = {
Expand All @@ -72,7 +76,7 @@ const KEEP_STATE = {
keepSubmitCount: true,
keepDirty: true,
keepErrors: true,
// keepDirtyValues: true,
// keepDirtyValues: true,
}

export function Form<FV extends FormValues>({
Expand All @@ -85,6 +89,7 @@ export function Form<FV extends FormValues>({
validateOnMount,
validationSchema,
enableReinitialize = true,
confirmOnNavigate = true,
}: PropsWithChildren<FormProps<FV>>): JSX.Element {
const fc = useForm({
mode: 'onBlur',
Expand Down Expand Up @@ -134,6 +139,30 @@ export function Form<FV extends FormValues>({
[onSubmit, extCtx]
)

// Ripped from here: https://www.wpeform.io/blog/exit-prompt-on-window-close-react-app/
useEffect(() => {
if (isSSR || !confirmOnNavigate) return

// the handler for actually showing the prompt
// https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload
const handler = (event: BeforeUnloadEvent) => {
event.preventDefault()
event.returnValue = ''
}

// if the form is NOT unchanged, then set the onbeforeunload
if (fc.formState.isDirty) {
window.addEventListener('beforeunload', handler)
// clean it up, if the dirty state changes
return () => {
window.removeEventListener('beforeunload', handler)
}
}
// since this is not dirty, don't do anything
// eslint-disable-next-line @typescript-eslint/no-empty-function
return () => {}
}, [fc.formState.isDirty])

Check warning on line 164 in src/form.tsx

View workflow job for this annotation

GitHub Actions / tests

React Hook useEffect has a missing dependency: 'confirmOnNavigate'. Either include it or remove the dependency array

return (
<FormProvider {...extCtx}>
<form
Expand Down Expand Up @@ -232,7 +261,11 @@ export function SaveCancelBtn({
const fc = useFormContext()

const { isDirty, isSubmitting, isSubmitted } = useFormState()
const { isEnabled: isDeleting, setEnabled: setDeleting, setDisabled: setDeleteFinished } = useToggle()
const {
isEnabled: isDeleting,
setEnabled: setDeleting,
setDisabled: setDeleteFinished,
} = useToggle()

if (!onDelete && !showControls && !isDirty && !isSubmitted) {
return null
Expand Down

0 comments on commit 0a16779

Please sign in to comment.