fix: styles readOnly RichTextEditor, removes interactivity within when readOnly
This commit is contained in:
@@ -70,6 +70,7 @@ const RichText: React.FC<Props> = (props) => {
|
|||||||
const [enabledLeaves, setEnabledLeaves] = useState({});
|
const [enabledLeaves, setEnabledLeaves] = useState({});
|
||||||
const [initialValueKey, setInitialValueKey] = useState('');
|
const [initialValueKey, setInitialValueKey] = useState('');
|
||||||
const editorRef = useRef(null);
|
const editorRef = useRef(null);
|
||||||
|
const toolbarRef = useRef(null);
|
||||||
|
|
||||||
const renderElement = useCallback(({ attributes, children, element }) => {
|
const renderElement = useCallback(({ attributes, children, element }) => {
|
||||||
const matchedElement = enabledElements[element?.type];
|
const matchedElement = enabledElements[element?.type];
|
||||||
@@ -176,6 +177,17 @@ const RichText: React.FC<Props> = (props) => {
|
|||||||
setInitialValueKey(JSON.stringify(initialValue || ''));
|
setInitialValueKey(JSON.stringify(initialValue || ''));
|
||||||
}, [initialValue]);
|
}, [initialValue]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (loaded && readOnly) {
|
||||||
|
// disable interactions on all editor elements when read only
|
||||||
|
Array.from(editorRef.current.children).forEach((child) => {
|
||||||
|
const childAsElement = child as HTMLElement;
|
||||||
|
childAsElement.tabIndex = -1;
|
||||||
|
childAsElement.style.pointerEvents = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [loaded, readOnly]);
|
||||||
|
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -215,14 +227,14 @@ const RichText: React.FC<Props> = (props) => {
|
|||||||
editor={editor}
|
editor={editor}
|
||||||
value={valueToRender as any[]}
|
value={valueToRender as any[]}
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
if (val !== defaultValue && val !== value) {
|
if (!readOnly && val !== defaultValue && val !== value) {
|
||||||
setValue(val);
|
setValue(val);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={`${baseClass}__wrapper`}>
|
<div className={`${baseClass}__wrapper`}>
|
||||||
<div className={`${baseClass}__toolbar`}>
|
<div className={`${baseClass}__toolbar`} ref={toolbarRef}>
|
||||||
<div className={`${baseClass}__toolbar-wrap`}>
|
<div className={`${baseClass}__toolbar-wrap`} tabIndex={readOnly ? -1 : undefined}>
|
||||||
{elements.map((element, i) => {
|
{elements.map((element, i) => {
|
||||||
let elementName: string;
|
let elementName: string;
|
||||||
if (typeof element === 'object' && element?.name) elementName = element.name;
|
if (typeof element === 'object' && element?.name) elementName = element.name;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
.rich-text {
|
.rich-text {
|
||||||
margin-bottom: base(2);
|
margin-bottom: base(2);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
isolation: isolate;
|
||||||
|
|
||||||
&__toolbar {
|
&__toolbar {
|
||||||
@include blur-bg(var(--theme-elevation-0));
|
@include blur-bg(var(--theme-elevation-0));
|
||||||
@@ -104,6 +105,25 @@
|
|||||||
background-color: var(--theme-elevation-150);
|
background-color: var(--theme-elevation-150);
|
||||||
padding: base(.5);
|
padding: base(.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rich-text__toolbar {
|
||||||
|
pointer-events: none;
|
||||||
|
position: relative;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: ' ';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: var(--theme-elevation-150);
|
||||||
|
opacity: .85;
|
||||||
|
z-index: 2;
|
||||||
|
backdrop-filter: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__button {
|
&__button {
|
||||||
|
|||||||
@@ -73,12 +73,46 @@ const RichTextFields: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'richTextReadOnly',
|
||||||
|
type: 'richText',
|
||||||
|
admin: {
|
||||||
|
readOnly: true,
|
||||||
|
link: {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'rel',
|
||||||
|
label: 'Rel Attribute',
|
||||||
|
type: 'select',
|
||||||
|
hasMany: true,
|
||||||
|
options: [
|
||||||
|
'noopener', 'noreferrer', 'nofollow',
|
||||||
|
],
|
||||||
|
admin: {
|
||||||
|
description: 'The rel attribute defines the relationship between a linked resource and the current document. This is a custom link field.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
upload: {
|
||||||
|
collections: {
|
||||||
|
uploads: {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'caption',
|
||||||
|
type: 'richText',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const richTextDoc = {
|
function generateRichText() {
|
||||||
selectHasMany: ['one', 'five'],
|
return [
|
||||||
richText: [
|
|
||||||
{
|
{
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@@ -220,7 +254,13 @@ export const richTextDoc = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
],
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const richTextDoc = {
|
||||||
|
selectHasMany: ['one', 'five'],
|
||||||
|
richText: generateRichText(),
|
||||||
|
richTextReadOnly: generateRichText(),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RichTextFields;
|
export default RichTextFields;
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ export default buildConfig({
|
|||||||
|
|
||||||
const richTextUploadIndex = richTextDocWithRelationship.richText.findIndex(({ type }) => type === 'upload');
|
const richTextUploadIndex = richTextDocWithRelationship.richText.findIndex(({ type }) => type === 'upload');
|
||||||
richTextDocWithRelationship.richText[richTextUploadIndex].value = { id: createdUploadDoc.id };
|
richTextDocWithRelationship.richText[richTextUploadIndex].value = { id: createdUploadDoc.id };
|
||||||
|
richTextDocWithRelationship.richTextReadOnly[richTextUploadIndex].value = { id: createdUploadDoc.id };
|
||||||
|
|
||||||
await payload.create({ collection: 'rich-text-fields', data: richTextDocWithRelationship });
|
await payload.create({ collection: 'rich-text-fields', data: richTextDocWithRelationship });
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user