From 32d6e0c875d4dfcfc7c9063096cab52b1855de38 Mon Sep 17 00:00:00 2001 From: Vixalie Date: Sun, 9 Mar 2025 22:14:05 +0800 Subject: [PATCH] prepare editable content component. --- src/components/EditableContent.module.css | 17 +++++++ src/components/EditableContent.tsx | 61 +++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/components/EditableContent.module.css create mode 100644 src/components/EditableContent.tsx diff --git a/src/components/EditableContent.module.css b/src/components/EditableContent.module.css new file mode 100644 index 0000000..9229a10 --- /dev/null +++ b/src/components/EditableContent.module.css @@ -0,0 +1,17 @@ +@layer components { + .editable_layout { + width: 100%; + min-width: 0; + display: flex; + flex-direction: row; + align-items: center; + gap: calc(var(--spacing) * 2); + line-height: 1.3em; + input { + flex: 1 0; + } + .placeholder { + color: color-mix(in oklch, var(--color-on-surface) 38%, transparent); + } + } +} diff --git a/src/components/EditableContent.tsx b/src/components/EditableContent.tsx new file mode 100644 index 0000000..44d3c3e --- /dev/null +++ b/src/components/EditableContent.tsx @@ -0,0 +1,61 @@ +import { Icon } from '@iconify/react/dist/iconify.js'; +import cx from 'clsx'; +import { FC, ReactHTMLElement, useCallback, useRef, useState } from 'react'; +import styles from './EditableContent.module.css'; + +type EditableContentProps = { + as?: keyof ReactHTMLElement; + value?: string | null; + onChange?: (value: string) => void; + placeholder?: string; + additionalClassName?: HTMLElement['className']; +}; + +const EditableContent: FC = ({ + as: Tag, + value, + onChange, + placeholder, + additionalClassName, +}) => { + const [isEditing, setEditing] = useState(false); + const formRef = useRef(null); + const cancelEdit = useCallback(() => { + setEditing(false); + formRef.current?.reset(); + }, []); + const handleSubmit = useCallback( + (data: FormData) => { + const newValue = data.get('value') as string; + if (newValue.length > 0 && newValue !== value) { + onChange?.(newValue); + } + cancelEdit(); + }, + [value], + ); + + return isEditing ? ( +
+ + + +
+ ) : ( +
+ {value ?? {placeholder}} + +
+ ); +}; + +export default EditableContent;