-
-
+
+ {label &&
+
{restProps.maxLength && (
{value?.length || 0}/{restProps.maxLength}
)}
-
-
-
setIsFocused(true)}
- onBlur={handleBlur}
- className={inputClasses}
- aria-label={label}
- />
-
- {value && isFocused && (
-
- )}
- {isValid && }
-
-
-
+
}
+ {viewMode && !isEditing ? renderViewMode() : renderEditMode()}
);
}
\ No newline at end of file
diff --git a/apps/web/src/components/common/form/FormQuillInput.tsx b/apps/web/src/components/common/form/FormQuillInput.tsx
new file mode 100644
index 0000000..7820f55
--- /dev/null
+++ b/apps/web/src/components/common/form/FormQuillInput.tsx
@@ -0,0 +1,79 @@
+import { useFormContext, Controller } from 'react-hook-form';
+import FormError from './FormError';
+import { useState } from 'react';
+import QuillEditor from '../editor/quill/QuillEditor';
+
+export interface FormQuillInputProps {
+ name: string;
+ label: string;
+ placeholder?: string;
+ maxLength?: number;
+ minLength?: number;
+ className?: string;
+ readOnly?: boolean;
+ maxRows?: number;
+ minRows?: number;
+}
+
+export function FormQuillInput({
+ name,
+ label,
+ placeholder,
+ maxLength,
+ minLength,
+ className,
+ readOnly = false,
+ maxRows = 10,
+ minRows = 4
+}: FormQuillInputProps) {
+ const [isFocused, setIsFocused] = useState(false);
+ const {
+ control,
+ formState: { errors },
+ trigger,
+ } = useFormContext();
+
+ const error = errors[name]?.message as string;
+
+ const handleBlur = async () => {
+
+ setIsFocused(false);
+ await trigger(name);
+ };
+ console.log(isFocused)
+ const containerClasses = `
+ w-full rounded-md border bg-white shadow-sm
+ transition-all duration-300 ease-out
+ ${isFocused
+ ? `ring-2 ring-opacity-50 ${error ? 'ring-red-200 border-red-500' : 'ring-blue-200 border-blue-500'}`
+ : 'border-gray-300'
+ }
+ ${className}
+ `.trim()
+ return (
+
+
+
+ (
+ setIsFocused(true)}
+ onBlur={handleBlur}
+ />
+ )}
+ />
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/apps/web/src/components/common/form/FormSelect.tsx b/apps/web/src/components/common/form/FormSelect.tsx
index 7b0795d..84eb27f 100644
--- a/apps/web/src/components/common/form/FormSelect.tsx
+++ b/apps/web/src/components/common/form/FormSelect.tsx
@@ -14,6 +14,7 @@ interface FormSelectProps {
label: string;
options: Option[];
placeholder?: string;
+ className?: string
}
const ANIMATIONS = {
@@ -31,7 +32,7 @@ const ANIMATIONS = {
}
};
-export function FormSelect({ name, label, options, placeholder = '请选择' }: FormSelectProps) {
+export function FormSelect({ name, label, options, placeholder = '请选择', className }: FormSelectProps) {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef
(null);
@@ -56,16 +57,17 @@ export function FormSelect({ name, label, options, placeholder = '请选择' }:
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
- const getInputClasses = (hasError: boolean) => `
- w-full rounded-md border bg-white
+ const containerClasses = `
+ w-full rounded-md border bg-white shadow-sm
transition-all duration-300 ease-out
p-2 pr-8 outline-none cursor-pointer
- ${hasError ? 'border-red-500 focus:border-red-500 focus:ring-red-200'
- : 'border-gray-300 focus:border-blue-500 focus:ring-blue-200'}
- ${isOpen ? 'ring-2 ring-opacity-50' : ''}
- placeholder:text-gray-400 shadow-sm
- `;
-
+ ${isOpen
+ ? `ring-2 ring-opacity-50 ${error ? 'ring-red-200 border-red-500' : 'ring-blue-200 border-blue-500'}`
+ : 'border-gray-300'
+ }
+ placeholder:text-gray-400
+ ${className}
+ `;
return (