From 3a175a13f1fd5ba7f99a6dc7883116352a03ba0b Mon Sep 17 00:00:00 2001 From: Hannes Tiede <951466+toxsick@users.noreply.github.com> Date: Wed, 6 Nov 2024 13:01:53 +0100 Subject: [PATCH] fix(uniform): refactor form debug state handling --- .../src/Form/subcomponents/FormContext.tsx | 23 +++++++++++++- .../Form/subcomponents/FormDebugViewer.tsx | 30 ++++++++----------- packages/uniform/src/Input/Input.tsx | 17 +++++++---- .../Input/__snapshots__/Input.test.tsx.snap | 27 ----------------- .../FieldCopyTestIdButton.tsx | 12 +------- 5 files changed, 48 insertions(+), 61 deletions(-) diff --git a/packages/uniform/src/Form/subcomponents/FormContext.tsx b/packages/uniform/src/Form/subcomponents/FormContext.tsx index c52723cb..039ce617 100644 --- a/packages/uniform/src/Form/subcomponents/FormContext.tsx +++ b/packages/uniform/src/Form/subcomponents/FormContext.tsx @@ -5,6 +5,8 @@ import type { FieldValues, SubmitHandler } from 'react-hook-form'; import React, { useMemo, useState } from 'react'; import { FormProvider as HookFormProvider, useForm } from 'react-hook-form'; +import { useLocalStorage } from '@fuf-stack/pixels'; + /** * recursively removes all fields that are null or undefined before * the form data is passed to the veto validation function @@ -17,6 +19,8 @@ export const removeNullishFields = (obj: Record) => { ); }; +type DebugMode = 'debug' | 'debug-testids' | 'off'; + /** * The `UniformContext` provides control over the form's submission behavior and may optionally include * a Veto validation schema for form validation. @@ -31,12 +35,18 @@ export const removeNullishFields = (obj: Record) => { * or access the validation schema for managing form validation logic. */ export const UniformContext = React.createContext<{ + /** Form debug mode enabled or not */ + debugMode: DebugMode; /** Function to update if the form can currently be submitted */ preventSubmit: (prevent: boolean) => void; + /** Setter to enable or disable form debug mode */ + setDebugMode: (debugMode: DebugMode) => void; /** Optional Veto validation schema instance for form validation */ validation?: VetoInstance; }>({ + debugMode: 'off', preventSubmit: () => undefined, + setDebugMode: () => undefined, validation: undefined, }); @@ -56,10 +66,13 @@ interface FormProviderProps { validationTrigger: 'onChange' | 'onBlur' | 'onSubmit' | 'onTouched' | 'all'; } +const LOCALSTORAGE_DEBUG_MODE_KEY = 'uniform:debug-mode'; + /** * FormProvider component provides: * - The veto validation schema context * - Submit handler creation and submission control with preventSubmit + * - Form Debug Mode state * - React Hook Form context */ const FormProvider: React.FC = ({ @@ -72,16 +85,24 @@ const FormProvider: React.FC = ({ // Control if the form can currently be submitted const [preventSubmit, setPreventSubmit] = useState(false); + // Form Debug mode state is handled in the form context + const [debugMode, setDebugMode] = useLocalStorage( + LOCALSTORAGE_DEBUG_MODE_KEY, + 'off', + ); + // Memoize the context value to prevent re-renders const contextValue = useMemo( () => ({ + debugMode, preventSubmit: (prevent: boolean) => { setPreventSubmit(prevent); }, + setDebugMode, validation, }), // eslint-disable-next-line react-hooks/exhaustive-deps - [], + [debugMode], ); // Initialize react hook form diff --git a/packages/uniform/src/Form/subcomponents/FormDebugViewer.tsx b/packages/uniform/src/Form/subcomponents/FormDebugViewer.tsx index 8b773bb7..a776f414 100644 --- a/packages/uniform/src/Form/subcomponents/FormDebugViewer.tsx +++ b/packages/uniform/src/Form/subcomponents/FormDebugViewer.tsx @@ -5,7 +5,7 @@ import { FaTimes } from 'react-icons/fa'; import { FaBug, FaBullseye } from 'react-icons/fa6'; import { cn } from '@fuf-stack/pixel-utils'; -import { Button, Card, Json, useLocalStorage } from '@fuf-stack/pixels'; +import { Button, Card, Json } from '@fuf-stack/pixels'; import { useFormContext } from '../../hooks'; @@ -14,28 +14,22 @@ interface FormDebugViewerProps { className?: string; } -const LOCALSTORAGE_DEBUG_KEY = 'uniform:form-debug-enabled'; -const LOCALSTORAGE_COPY_TEST_ID_KEY = 'uniform:form-debug-copy-test-id-enabled'; - /** Renders a form debug panel with information about the current form state */ const FormDebugViewer = ({ className = undefined }: FormDebugViewerProps) => { const { - watch, + debugMode, formState: { dirtyFields, isValid, isSubmitting }, + setDebugMode, validation, + watch, } = useFormContext(); - const [debug, setDebug] = useLocalStorage(LOCALSTORAGE_DEBUG_KEY, false); - const [copyTestId, setCopyTestId] = useLocalStorage( - LOCALSTORAGE_COPY_TEST_ID_KEY, - false, - ); - const [validationErrors, setValidationErrors] = useState< VetoError['errors'] | null >(null); const formValues = watch(); + const debugTestIdsEnabled = debugMode === 'debug-testids'; useEffect( () => { @@ -51,11 +45,11 @@ const FormDebugViewer = ({ className = undefined }: FormDebugViewerProps) => { [JSON.stringify(formValues)], ); - if (!debug) { + if (!debugMode || debugMode === 'off') { return ( { - const { control, getFieldState } = useFormContext(); + const { control, debugMode, getFieldState } = useFormContext(); const { error, invalid, required, testId } = getFieldState(name, _testId); + const showTestIdCopyButton = debugMode === 'debug-testids'; + const showLabel = label || showTestIdCopyButton; + return ( - {label} - - + showLabel && ( + <> + {label} + {showTestIdCopyButton && ( + + )} + + ) } labelPlacement="outside" name={name} diff --git a/packages/uniform/src/Input/__snapshots__/Input.test.tsx.snap b/packages/uniform/src/Input/__snapshots__/Input.test.tsx.snap index 6be4829d..e0475c8a 100644 --- a/packages/uniform/src/Input/__snapshots__/Input.test.tsx.snap +++ b/packages/uniform/src/Input/__snapshots__/Input.test.tsx.snap @@ -13,8 +13,6 @@ exports[`Story Snapshots > Default 1`] = ` class="group flex flex-col data-[hidden=true]:hidden w-full relative justify-end data-[has-label=true]:mt-[calc(theme(fontSize.small)_+_10px)]" data-filled="true" data-filled-within="true" - data-has-elements="true" - data-has-label="true" data-slot="base" >
Default 1`] = ` data-slot="input-wrapper" style="cursor: text;" > -