mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-18 07:52:23 +01:00
Add disabled style on text editor
This commit is contained in:
parent
f18c4a2ecd
commit
3a8671edbd
@ -1,4 +1,4 @@
|
||||
import React, { forwardRef, RefObject, useImperativeHandle, useRef } from 'react';
|
||||
import React, { forwardRef, RefObject, useEffect, useImperativeHandle, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useEditor, EditorContent, Editor } from '@tiptap/react';
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
@ -12,7 +12,6 @@ import { MenuBar } from './menu-bar';
|
||||
import { WarningOctagon } from 'phosphor-react';
|
||||
|
||||
interface FabTextEditorProps {
|
||||
label?: string,
|
||||
paragraphTools?: boolean,
|
||||
content?: string,
|
||||
limit?: number,
|
||||
@ -21,7 +20,7 @@ interface FabTextEditorProps {
|
||||
onChange?: (content: string) => void,
|
||||
placeholder?: string,
|
||||
error?: string,
|
||||
readOnly?: boolean,
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export interface FabTextEditorRef {
|
||||
@ -31,7 +30,7 @@ export interface FabTextEditorRef {
|
||||
/**
|
||||
* This component is a WYSIWYG text editor
|
||||
*/
|
||||
export const FabTextEditor: React.ForwardRefRenderFunction<FabTextEditorRef, FabTextEditorProps> = ({ label, paragraphTools, content, limit = 400, video, image, onChange, placeholder, error, readOnly = false }, ref: RefObject<FabTextEditorRef>) => {
|
||||
export const FabTextEditor: React.ForwardRefRenderFunction<FabTextEditorRef, FabTextEditorProps> = ({ paragraphTools, content, limit = 400, video, image, onChange, placeholder, error, disabled = false }, ref: RefObject<FabTextEditorRef>) => {
|
||||
const { t } = useTranslation('shared');
|
||||
const placeholderText = placeholder || t('app.shared.text_editor.text_placeholder');
|
||||
// TODO: Add ctrl+click on link to visit
|
||||
@ -40,7 +39,7 @@ export const FabTextEditor: React.ForwardRefRenderFunction<FabTextEditorRef, Fab
|
||||
// the methods in useImperativeHandle are exposed to the parent component
|
||||
useImperativeHandle(ref, () => ({
|
||||
focus () {
|
||||
focusEditor();
|
||||
editorRef.current?.commands?.focus();
|
||||
}
|
||||
}), []);
|
||||
|
||||
@ -71,41 +70,34 @@ export const FabTextEditor: React.ForwardRefRenderFunction<FabTextEditorRef, Fab
|
||||
}
|
||||
})
|
||||
],
|
||||
editable: !readOnly,
|
||||
content,
|
||||
onUpdate: ({ editor }) => {
|
||||
onChange(editor.getHTML());
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Callback triggered when the label is clicked: we want to focus the text edition zone
|
||||
*/
|
||||
const focusEditor = () => {
|
||||
editorRef.current?.commands?.focus();
|
||||
};
|
||||
useEffect(() => {
|
||||
editor?.setEditable(!disabled);
|
||||
}, [disabled]);
|
||||
|
||||
// bind the editor to the ref, once it is ready
|
||||
if (!editor) return null;
|
||||
editorRef.current = editor;
|
||||
|
||||
return (
|
||||
<>
|
||||
{label && <label onClick={focusEditor} className="fab-textEditor-label">{label}</label>}
|
||||
<div className="fab-textEditor">
|
||||
<MenuBar editor={editor} paragraphTools={paragraphTools} video={video} image={image} disabled={readOnly} />
|
||||
<EditorContent editor={editor} />
|
||||
<div className="fab-textEditor-character-count">
|
||||
{editor?.storage.characterCount.characters()} / {limit}
|
||||
</div>
|
||||
{error &&
|
||||
<div className="fab-textEditor-error">
|
||||
<WarningOctagon size={24} />
|
||||
<p className="">{error}</p>
|
||||
</div>
|
||||
}
|
||||
<div className={`fab-textEditor ${disabled && 'is-disabled'}`}>
|
||||
<MenuBar editor={editor} paragraphTools={paragraphTools} video={video} image={image} disabled={disabled} />
|
||||
<EditorContent editor={editor} />
|
||||
<div className="fab-textEditor-character-count">
|
||||
{editor?.storage.characterCount.characters()} / {limit}
|
||||
</div>
|
||||
</>
|
||||
{error &&
|
||||
<div className="fab-textEditor-error">
|
||||
<WarningOctagon size={24} />
|
||||
<p className="">{error}</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -9,7 +9,6 @@ export interface AbstractFormItemProps<TFieldValues> extends PropsWithChildren<A
|
||||
tooltip?: ReactNode,
|
||||
className?: string,
|
||||
disabled?: boolean|((id: string) => boolean),
|
||||
readOnly?: boolean
|
||||
onLabelClick?: (event: React.MouseEvent<HTMLLabelElement, MouseEvent>) => void,
|
||||
}
|
||||
|
||||
@ -17,7 +16,7 @@ export interface AbstractFormItemProps<TFieldValues> extends PropsWithChildren<A
|
||||
* This abstract component should not be used directly.
|
||||
* Other forms components that are intended to be used with react-hook-form must extend this component.
|
||||
*/
|
||||
export const AbstractFormItem = <TFieldValues extends FieldValues>({ id, label, tooltip, className, disabled, readOnly, error, warning, rules, formState, onLabelClick, children }: AbstractFormItemProps<TFieldValues>) => {
|
||||
export const AbstractFormItem = <TFieldValues extends FieldValues>({ id, label, tooltip, className, disabled, error, warning, rules, formState, onLabelClick, children }: AbstractFormItemProps<TFieldValues>) => {
|
||||
const [isDirty, setIsDirty] = useState<boolean>(false);
|
||||
const [fieldError, setFieldError] = useState<{ message: string }>(error);
|
||||
const [isDisabled, setIsDisabled] = useState<boolean>(false);
|
||||
@ -46,7 +45,6 @@ export const AbstractFormItem = <TFieldValues extends FieldValues>({ id, label,
|
||||
`${isDirty && fieldError ? 'is-incorrect' : ''}`,
|
||||
`${isDirty && warning ? 'is-warned' : ''}`,
|
||||
`${rules && rules.required ? 'is-required' : ''}`,
|
||||
`${readOnly ? 'is-readonly' : ''}`,
|
||||
`${isDisabled ? 'is-disabled' : ''}`
|
||||
].join(' ');
|
||||
|
||||
|
@ -23,7 +23,7 @@ interface FormInputProps<TFieldValues, TInputType> extends FormComponent<TFieldV
|
||||
/**
|
||||
* This component is a template for an input component to use within React Hook Form
|
||||
*/
|
||||
export const FormInput = <TFieldValues extends FieldValues, TInputType>({ id, register, label, tooltip, defaultValue, icon, className, rules, readOnly, disabled, type, addOn, addOnAction, addOnClassName, placeholder, error, warning, formState, step, onChange, debounce, accept }: FormInputProps<TFieldValues, TInputType>) => {
|
||||
export const FormInput = <TFieldValues extends FieldValues, TInputType>({ id, register, label, tooltip, defaultValue, icon, className, rules, disabled, type, addOn, addOnAction, addOnClassName, placeholder, error, warning, formState, step, onChange, debounce, accept }: FormInputProps<TFieldValues, TInputType>) => {
|
||||
/**
|
||||
* Debounced (ie. temporised) version of the 'on change' callback.
|
||||
*/
|
||||
@ -52,7 +52,7 @@ export const FormInput = <TFieldValues extends FieldValues, TInputType>({ id, re
|
||||
return (
|
||||
<AbstractFormItem id={id} formState={formState} label={label}
|
||||
className={classNames} tooltip={tooltip}
|
||||
disabled={disabled} readOnly={readOnly}
|
||||
disabled={disabled}
|
||||
rules={rules} error={error} warning={warning}>
|
||||
{icon && <span className="icon">{icon}</span>}
|
||||
<input id={id}
|
||||
@ -66,7 +66,6 @@ export const FormInput = <TFieldValues extends FieldValues, TInputType>({ id, re
|
||||
type={type}
|
||||
step={step}
|
||||
disabled={typeof disabled === 'function' ? disabled(id) : disabled}
|
||||
readOnly={readOnly}
|
||||
placeholder={placeholder}
|
||||
accept={accept} />
|
||||
{addOn && <span onClick={addOnAction} className={`addon ${addOnClassName || ''} ${addOnAction ? 'is-btn' : ''}`}>{addOn}</span>}
|
||||
|
@ -27,15 +27,15 @@ type selectOption<TOptionValue> = { value: TOptionValue, label: string };
|
||||
* This component is a wrapper around react-select to use with react-hook-form.
|
||||
* It is a multi-select component.
|
||||
*/
|
||||
export const FormMultiSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, tooltip, className, control, placeholder, options, valuesDefault, error, rules, disabled, onChange, formState, readOnly, warning, expectedResult, creatable }: FormSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
||||
export const FormMultiSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, tooltip, className, control, placeholder, options, valuesDefault, error, rules, disabled, onChange, formState, warning, expectedResult, creatable }: FormSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
||||
const [isDisabled, setIsDisabled] = React.useState<boolean>(false);
|
||||
const [allOptions, setAllOptions] = React.useState<Array<selectOption<TOptionValue>>>(options);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof disabled === 'function') {
|
||||
setIsDisabled(disabled(id) || readOnly);
|
||||
setIsDisabled(disabled(id));
|
||||
} else {
|
||||
setIsDisabled(disabled || readOnly);
|
||||
setIsDisabled(disabled);
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
@ -94,7 +94,7 @@ export const FormMultiSelect = <TFieldValues extends FieldValues, TContext exten
|
||||
return (
|
||||
<AbstractFormItem id={id} formState={formState} label={label}
|
||||
className={`form-multi-select ${className || ''}`} tooltip={tooltip}
|
||||
disabled={disabled} readOnly={readOnly}
|
||||
disabled={disabled}
|
||||
rules={rules} error={error} warning={warning}>
|
||||
<Controller name={id as FieldPath<TFieldValues>}
|
||||
control={control}
|
||||
@ -122,6 +122,5 @@ export const FormMultiSelect = <TFieldValues extends FieldValues, TContext exten
|
||||
FormMultiSelect.defaultProps = {
|
||||
expectedResult: 'array',
|
||||
creatable: false,
|
||||
readOnly: false,
|
||||
disabled: false
|
||||
};
|
||||
|
@ -18,15 +18,15 @@ interface FormRichTextProps<TFieldValues, TContext extends object> extends FormC
|
||||
/**
|
||||
* This component is a rich-text editor to use with react-hook-form.
|
||||
*/
|
||||
export const FormRichText = <TFieldValues extends FieldValues, TContext extends object>({ id, label, tooltip, className, control, valueDefault, error, warning, rules, disabled = false, readOnly = false, formState, limit, paragraphTools, video, image }: FormRichTextProps<TFieldValues, TContext>) => {
|
||||
export const FormRichText = <TFieldValues extends FieldValues, TContext extends object>({ id, label, tooltip, className, control, valueDefault, error, warning, rules, disabled = false, formState, limit, paragraphTools, video, image }: FormRichTextProps<TFieldValues, TContext>) => {
|
||||
const textEditorRef = React.useRef<FabTextEditorRef>();
|
||||
const [isDisabled, setIsDisabled] = React.useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof disabled === 'function') {
|
||||
setIsDisabled(disabled(id) || readOnly);
|
||||
setIsDisabled(disabled(id));
|
||||
} else {
|
||||
setIsDisabled(disabled || readOnly);
|
||||
setIsDisabled(disabled);
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
@ -56,7 +56,7 @@ export const FormRichText = <TFieldValues extends FieldValues, TContext extends
|
||||
paragraphTools={paragraphTools}
|
||||
video={video}
|
||||
image={image}
|
||||
readOnly={isDisabled}
|
||||
disabled={isDisabled}
|
||||
ref={textEditorRef} />
|
||||
} />
|
||||
</AbstractFormItem>
|
||||
|
@ -26,14 +26,14 @@ type selectOption<TOptionValue> = { value: TOptionValue, label: string };
|
||||
/**
|
||||
* This component is a wrapper for react-select to use with react-hook-form
|
||||
*/
|
||||
export const FormSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, tooltip, className, control, placeholder, options, valueDefault, error, warning, rules, disabled = false, onChange, readOnly = false, clearable = false, formState, creatable = false }: FormSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
||||
export const FormSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, tooltip, className, control, placeholder, options, valueDefault, error, warning, rules, disabled = false, onChange, clearable = false, formState, creatable = false }: FormSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
||||
const [isDisabled, setIsDisabled] = React.useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof disabled === 'function') {
|
||||
setIsDisabled(disabled(id) || readOnly);
|
||||
setIsDisabled(disabled(id));
|
||||
} else {
|
||||
setIsDisabled(disabled || readOnly);
|
||||
setIsDisabled(disabled);
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
@ -54,7 +54,7 @@ export const FormSelect = <TFieldValues extends FieldValues, TContext extends ob
|
||||
<AbstractFormItem id={id} label={label} tooltip={tooltip}
|
||||
className={`form-select ${className || ''}`} formState={formState}
|
||||
error={error} warning={warning} rules={rules}
|
||||
disabled={disabled} readOnly={readOnly}>
|
||||
disabled={disabled}>
|
||||
<Controller name={id as FieldPath<TFieldValues>}
|
||||
control={control}
|
||||
defaultValue={valueDefault as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>}
|
||||
|
@ -14,7 +14,7 @@ interface FormSwitchProps<TFieldValues, TContext extends object> extends FormCon
|
||||
/**
|
||||
* This component is a wrapper for react-switch, to use with react-hook-form.
|
||||
*/
|
||||
export const FormSwitch = <TFieldValues, TContext extends object>({ id, label, tooltip, className, error, rules, disabled, control, defaultValue, formState, readOnly, warning, onChange }: FormSwitchProps<TFieldValues, TContext>) => {
|
||||
export const FormSwitch = <TFieldValues, TContext extends object>({ id, label, tooltip, className, error, rules, disabled, control, defaultValue, formState, warning, onChange }: FormSwitchProps<TFieldValues, TContext>) => {
|
||||
/**
|
||||
* The following callback will trigger the onChange callback, if it was passed to this component,
|
||||
* when the selected option changes.
|
||||
@ -28,7 +28,7 @@ export const FormSwitch = <TFieldValues, TContext extends object>({ id, label, t
|
||||
return (
|
||||
<AbstractFormItem id={id} formState={formState} label={label}
|
||||
className={`form-switch ${className || ''}`} tooltip={tooltip}
|
||||
disabled={disabled} readOnly={readOnly}
|
||||
disabled={disabled}
|
||||
rules={rules} error={error} warning={warning}>
|
||||
<Controller name={id as FieldPath<TFieldValues>}
|
||||
control={control}
|
||||
@ -43,8 +43,7 @@ export const FormSwitch = <TFieldValues, TContext extends object>({ id, label, t
|
||||
height={19}
|
||||
width={40}
|
||||
ref={ref}
|
||||
disabled={typeof disabled === 'function' ? disabled(id) : disabled}
|
||||
readOnly={readOnly} />
|
||||
disabled={typeof disabled === 'function' ? disabled(id) : disabled} />
|
||||
} />
|
||||
</AbstractFormItem>
|
||||
);
|
||||
|
@ -212,4 +212,13 @@
|
||||
}
|
||||
p { margin: 0; }
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
.ProseMirror {
|
||||
resize: none;
|
||||
}
|
||||
button {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,7 @@
|
||||
border: 0;
|
||||
display: block;
|
||||
}
|
||||
&.is-disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user