mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2026-03-01 12:44:17 +00:00
159 lines
4.8 KiB
TypeScript
159 lines
4.8 KiB
TypeScript
import { useEffect, useMemo, useRef, useState } from 'react'
|
|
import { SimpleMdeReact } from 'react-simplemde-editor'
|
|
|
|
import type SimpleMDE from 'easymde'
|
|
import type { InputHTMLAttributes } from 'react'
|
|
|
|
interface TextAreaProps {
|
|
labelTitle?: string
|
|
labelStyle?: string
|
|
containerStyle?: string
|
|
dataField?: string
|
|
inputStyle?: string
|
|
defaultValue: string
|
|
placeholder?: string
|
|
required?: boolean
|
|
size?: string
|
|
updateFormValue?: (value: string) => void
|
|
}
|
|
|
|
/**
|
|
* @category Input
|
|
*/
|
|
export function TextAreaInput({
|
|
labelTitle,
|
|
dataField,
|
|
labelStyle,
|
|
containerStyle,
|
|
inputStyle,
|
|
defaultValue,
|
|
placeholder,
|
|
required = true,
|
|
size,
|
|
updateFormValue,
|
|
}: TextAreaProps) {
|
|
const ref = useRef<HTMLDivElement>(null)
|
|
const [inputValue, setInputValue] = useState<string>(defaultValue)
|
|
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
|
|
const [containerHeight, setContainerHeight] = useState<string>('100%')
|
|
|
|
useEffect(() => {
|
|
if (containerRef.current) {
|
|
const height = containerRef.current.offsetHeight
|
|
setContainerHeight(`${height - 200}px`)
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
setInputValue(defaultValue)
|
|
}, [defaultValue])
|
|
|
|
const handleChange = (value: string) => {
|
|
const newValue = value
|
|
setInputValue(newValue)
|
|
if (updateFormValue) {
|
|
updateFormValue(newValue)
|
|
}
|
|
}
|
|
|
|
const options = useMemo(() => {
|
|
return {
|
|
status: false,
|
|
lineNumbers: false,
|
|
minHeight: size === 'small' ? '100%' : '100%',
|
|
maxHeight: size === 'small' ? '30px' : containerHeight,
|
|
forceSync: true,
|
|
/*
|
|
autoDownloadFontAwesome?: boolean;
|
|
autofocus?: boolean;
|
|
autosave?: AutoSaveOptions;
|
|
autoRefresh?: boolean | { delay: number; };
|
|
blockStyles?: BlockStyleOptions;
|
|
element?: HTMLElement;
|
|
forceSync?: boolean;
|
|
hideIcons?: ReadonlyArray<ToolbarButton>;
|
|
indentWithTabs?: boolean;
|
|
initialValue?: string;
|
|
insertTexts?: InsertTextOptions;
|
|
lineWrapping?: boolean;
|
|
minHeight?: string;
|
|
maxHeight?: string;
|
|
parsingConfig?: ParsingOptions;
|
|
placeholder?: string;
|
|
previewClass?: string | ReadonlyArray<string>;
|
|
previewImagesInEditor?: boolean;
|
|
imagesPreviewHandler?: (src: string) => string,
|
|
previewRender?: (markdownPlaintext: string, previewElement: HTMLElement) => string | null;
|
|
promptURLs?: boolean;
|
|
renderingConfig?: RenderingOptions;
|
|
shortcuts?: Shortcuts;
|
|
showIcons?: ReadonlyArray<ToolbarButton>;
|
|
spellChecker?: boolean | ((options: SpellCheckerOptions) => void);
|
|
inputStyle?: 'textarea' | 'contenteditable';
|
|
nativeSpellcheck?: boolean;
|
|
sideBySideFullscreen?: boolean;
|
|
status?: boolean | ReadonlyArray<string | StatusBarItem>;
|
|
styleSelectedText?: boolean;
|
|
tabSize?: number;
|
|
toolbar?: boolean | ReadonlyArray<'|' | ToolbarButton | ToolbarIcon | ToolbarDropdownIcon>;
|
|
toolbarTips?: boolean;
|
|
toolbarButtonClassPrefix?: string;
|
|
onToggleFullScreen?: (goingIntoFullScreen: boolean) => void;
|
|
theme?: string;
|
|
scrollbarStyle?: string;
|
|
unorderedListStyle?: '*' | '-' | '+';
|
|
|
|
uploadImage?: boolean;
|
|
imageMaxSize?: number;
|
|
imageAccept?: string;
|
|
imageUploadFunction?: (file: File, onSuccess: (url: string) => void, onError: (error: string) => void) => void;
|
|
imageUploadEndpoint?: string;
|
|
imagePathAbsolute?: boolean;
|
|
imageCSRFToken?: string;
|
|
imageCSRFName?: string;
|
|
imageCSRFHeader?: boolean;
|
|
imageTexts?: ImageTextsOptions;
|
|
imageInputName?: string
|
|
errorMessages?: ImageErrorTextsOptions;
|
|
errorCallback?: (errorMessage: string) => void;
|
|
|
|
promptTexts?: PromptTexts;
|
|
syncSideBySidePreviewScroll?: boolean;
|
|
|
|
overlayMode?: OverlayModeOptions;
|
|
|
|
direction?: 'ltr' | 'rtl';
|
|
*/
|
|
} as SimpleMDE.Options
|
|
}, [containerHeight, size])
|
|
|
|
return (
|
|
<div ref={containerRef} className={`tw:form-control ${containerStyle ?? ''}`}>
|
|
{labelTitle ? (
|
|
<label className='tw:label'>
|
|
<span className={`tw:label-text tw:text-base-content ${labelStyle ?? ''}`}>
|
|
{labelTitle}
|
|
{required && !inputValue ? ' (this field is required)' : null}
|
|
</span>
|
|
</label>
|
|
) : null}
|
|
<SimpleMdeReact
|
|
textareaProps={
|
|
{
|
|
required,
|
|
} as InputHTMLAttributes<HTMLTextAreaElement>
|
|
}
|
|
ref={ref}
|
|
id={dataField}
|
|
value={inputValue}
|
|
placeholder={placeholder ?? ''}
|
|
onChange={handleChange}
|
|
options={options}
|
|
className={`${inputStyle ?? ''}`}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|