Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change read only mode API to editable mode #2912

Merged
merged 3 commits into from
Sep 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default function ExcalidrawComponent({
}): JSX.Element {
const [editor] = useLexicalComposerContext();
const [isModalOpen, setModalOpen] = useState<boolean>(
data === '[]' && !editor.isReadOnly(),
data === '[]' && editor.isEditable(),
);
const imageContainerRef = useRef<HTMLImageElement | null>(null);
const buttonRef = useRef<HTMLButtonElement | null>(null);
Expand Down Expand Up @@ -67,9 +67,9 @@ export default function ExcalidrawComponent({
// Set editor to readOnly if excalidraw is open to prevent unwanted changes
useEffect(() => {
if (isModalOpen) {
editor.setReadOnly(true);
editor.setEditable(false);
} else {
editor.setReadOnly(false);
editor.setEditable(true);
}
}, [isModalOpen, editor]);

Expand Down Expand Up @@ -124,7 +124,7 @@ export default function ExcalidrawComponent({
}, [editor, nodeKey]);

const setData = (newData: ReadonlyArray<ExcalidrawElementFragment>) => {
if (editor.isReadOnly()) {
if (!editor.isEditable()) {
return;
}
return editor.update(() => {
Expand Down Expand Up @@ -158,7 +158,7 @@ export default function ExcalidrawComponent({
isShown={isModalOpen}
onDelete={deleteNode}
onSave={(newData) => {
editor.setReadOnly(false);
editor.setEditable(true);
setData(newData);
setModalOpen(false);
}}
Expand Down
20 changes: 10 additions & 10 deletions packages/lexical-playground/src/plugins/ActionsPlugin/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export default function ActionsPlugin({
isRichText: boolean;
}): JSX.Element {
const [editor] = useLexicalComposerContext();
const [isReadOnly, setIsReadOnly] = useState(() => editor.isReadOnly());
const [isEditable, setIsEditable] = useState(() => editor.isEditable());
const [isSpeechToText, setIsSpeechToText] = useState(false);
const [connected, setConnected] = useState(false);
const [isEditorEmpty, setIsEditorEmpty] = useState(true);
Expand All @@ -89,8 +89,8 @@ export default function ActionsPlugin({

useEffect(() => {
return mergeRegister(
editor.registerReadOnlyListener((readOnly) => {
setIsReadOnly(readOnly);
editor.registerEditableListener((editable) => {
setIsEditable(editable);
}),
editor.registerCommand<boolean>(
CONNECTED_COMMAND,
Expand All @@ -110,7 +110,7 @@ export default function ActionsPlugin({
// If we are in read only mode, send the editor state
// to server and ask for validation if possible.
if (
isReadOnly &&
!isEditable &&
dirtyElements.size > 0 &&
!tags.has('historic') &&
!tags.has('collaboration')
Expand All @@ -134,7 +134,7 @@ export default function ActionsPlugin({
});
},
);
}, [editor, isReadOnly]);
}, [editor, isEditable]);

const handleMarkdownToggle = useCallback(() => {
editor.update(() => {
Expand Down Expand Up @@ -208,17 +208,17 @@ export default function ActionsPlugin({
<i className="clear" />
</button>
<button
className={`action-button ${isReadOnly ? 'unlock' : 'lock'}`}
className={`action-button ${!isEditable ? 'unlock' : 'lock'}`}
onClick={() => {
// Send latest editor state to commenting validation server
if (!isReadOnly) {
if (isEditable) {
sendEditorState(editor);
}
editor.setReadOnly(!editor.isReadOnly());
editor.setEditable(!editor.isEditable());
}}
title="Read-Only Mode"
aria-label={`${isReadOnly ? 'Unlock' : 'Lock'} read-only mode`}>
<i className={isReadOnly ? 'unlock' : 'lock'} />
aria-label={`${!isEditable ? 'Unlock' : 'Lock'} read-only mode`}>
<i className={!isEditable ? 'unlock' : 'lock'} />
</button>
<button
className="action-button"
Expand Down
4 changes: 2 additions & 2 deletions packages/lexical-react/src/LexicalCheckListPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export function CheckListPlugin(): null {
(event) => {
const activeItem = getActiveCheckListItem();

if (activeItem != null && !editor.isReadOnly()) {
if (activeItem != null && editor.isEditable()) {
editor.update(() => {
const listItemNode = $getNearestNodeFromDOMNode(activeItem);

Expand Down Expand Up @@ -200,7 +200,7 @@ function handleClick(event: Event) {
const domNode = event.target as HTMLElement;
const editor = findEditor(domNode);

if (editor != null && !editor.isReadOnly()) {
if (editor != null && editor.isEditable()) {
editor.update(() => {
if (event.target) {
const node = $getNearestNodeFromDOMNode(domNode);
Expand Down
8 changes: 4 additions & 4 deletions packages/lexical-react/src/LexicalComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type Props = {
namespace: string;
nodes?: ReadonlyArray<Klass<LexicalNode>>;
onError: (error: Error, editor: LexicalEditor) => void;
readOnly?: boolean;
editable?: boolean;
theme?: EditorThemeClasses;
editorState?: InitialEditorStateType;
}>;
Expand All @@ -67,10 +67,10 @@ export function LexicalComposer({initialConfig, children}: Props): JSX.Element {

if (editor === null) {
const newEditor = createEditor({
editable: false,
namespace,
nodes,
onError: (error) => onError(error, newEditor),
readOnly: true,
theme,
});
initializeEditor(newEditor, initialEditorState);
Expand All @@ -87,9 +87,9 @@ export function LexicalComposer({initialConfig, children}: Props): JSX.Element {
);

useLayoutEffect(() => {
const isReadOnly = initialConfig.readOnly;
const isEditable = initialConfig.editable;
const [editor] = composerContext;
editor.setReadOnly(isReadOnly || false);
editor.setEditable(isEditable || true);

// We only do this for init
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
23 changes: 11 additions & 12 deletions packages/lexical-react/src/LexicalContentEditable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ export function ContentEditable({
testid,
}: Props): JSX.Element {
const [editor] = useLexicalComposerContext();

const [isReadOnly, setReadOnly] = useState(true);
const [isEditable, setEditable] = useState(true);

const ref = useCallback(
(rootElement: null | HTMLElement) => {
Expand All @@ -69,25 +68,25 @@ export function ContentEditable({
);

useLayoutEffect(() => {
setReadOnly(editor.isReadOnly());
return editor.registerReadOnlyListener((currentIsReadOnly) => {
setReadOnly(currentIsReadOnly);
setEditable(editor.isEditable());
return editor.registerEditableListener((currentIsEditable) => {
setEditable(currentIsEditable);
});
}, [editor]);

return (
<div
aria-activedescendant={isReadOnly ? null : ariaActiveDescendantID}
aria-autocomplete={isReadOnly ? null : ariaAutoComplete}
aria-controls={isReadOnly ? null : ariaControls}
aria-activedescendant={!isEditable ? null : ariaActiveDescendantID}
aria-autocomplete={!isEditable ? null : ariaAutoComplete}
aria-controls={!isEditable ? null : ariaControls}
aria-describedby={ariaDescribedBy}
aria-expanded={
isReadOnly ? null : role === 'combobox' ? !!ariaExpanded : null
!isEditable ? null : role === 'combobox' ? !!ariaExpanded : null
}
aria-label={ariaLabel}
aria-labelledby={ariaLabelledBy}
aria-multiline={ariaMultiline}
aria-owns={isReadOnly ? null : ariaOwneeID}
aria-owns={!isEditable ? null : ariaOwneeID}
aria-required={ariaRequired}
autoCapitalize={
autoCapitalize !== undefined ? String(autoCapitalize) : undefined
Expand All @@ -96,11 +95,11 @@ export function ContentEditable({
autoComplete={autoComplete}
autoCorrect={autoCorrect !== undefined ? String(autoCorrect) : undefined}
className={className}
contentEditable={!isReadOnly}
contentEditable={isEditable}
data-testid={testid}
id={id}
ref={ref}
role={isReadOnly ? undefined : role}
role={!isEditable ? undefined : role}
spellCheck={spellCheck}
style={style}
tabIndex={tabIndex}
Expand Down
4 changes: 2 additions & 2 deletions packages/lexical-react/src/shared/useCanShowPlaceholder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function canShowPlaceholderFromCurrentEditorState(
): boolean {
const currentCanShowPlaceholder = editor
.getEditorState()
.read($canShowPlaceholderCurry(editor.isComposing(), editor.isReadOnly()));
.read($canShowPlaceholderCurry(editor.isComposing(), editor.isEditable()));

return currentCanShowPlaceholder;
}
Expand All @@ -39,7 +39,7 @@ export function useCanShowPlaceholder(editor: LexicalEditor): boolean {
editor.registerUpdateListener(() => {
resetCanShowPlaceholder();
}),
editor.registerReadOnlyListener(() => {
editor.registerEditableListener(() => {
resetCanShowPlaceholder();
}),
);
Expand Down
8 changes: 4 additions & 4 deletions packages/lexical-text/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ export function $rootTextContent(): string {
export function $canShowPlaceholder(
isComposing: boolean,
// TODO 0.4 make mandatory
isReadOnly = false,
isEditable = true,
): boolean {
if (isReadOnly || !$isRootTextContentEmpty(isComposing, false)) {
if (!isEditable || !$isRootTextContentEmpty(isComposing, false)) {
return false;
}

Expand Down Expand Up @@ -257,9 +257,9 @@ export function $canShowPlaceholder(
export function $canShowPlaceholderCurry(
isEditorComposing: boolean,
// TODO 0.4 make mandatory
isReadOnly = false,
isEditable = true,
): () => boolean {
return () => $canShowPlaceholder(isEditorComposing, isReadOnly);
return () => $canShowPlaceholder(isEditorComposing, isEditable);
}

export type EntityMatch = {end: number; start: number};
Expand Down
16 changes: 8 additions & 8 deletions packages/lexical-website/docs/concepts/listeners.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,21 +98,21 @@ const removeMutationListener = editor.registerMutationListener(
removeMutationListener();
```

## `registerReadOnlyListener`
## `registerEditableListener`

Get notified when the editor's read only mode has changed. The editor's read only mode can be changed
via `editor.setReadOnly(boolean)`.
Get notified when the editor's mode has changed. The editor's mode can be changed
via `editor.setEditable(boolean)`.

```js
const removeReadOnlyListener = editor.registerReadOnlyListener(
(readOnly) => {
// The editor's read only mode is passed in!
console.log(readOnly);
const removeEditableListener = editor.registerEditableListener(
(editable) => {
// The editor's mode is passed in!
console.log(editable);
},
);

// Do not forget to unregister the listener when no longer needed!
removeReadOnlyListener();
removeEditableListener();
```

## `registerDecoratorListener`
Expand Down
20 changes: 10 additions & 10 deletions packages/lexical-website/docs/concepts/read-only.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
sidebar_position: 8
---

# Read Only Mode
# Read Model / Edit Mode

Lexical supports two modes:

Expand All @@ -20,43 +20,43 @@ In order to set the mode, this can be done on creation of the editor:

```js
const editor = createEditor({
readOnly: true,
editable: true,
...
})
```

If you're using `@lexical/react` this can be done on the `initialConfig` passed to `<LexicalComposer>`:

```jsx
<LexicalComposer initialConfig={{readOnly: true}}>
<LexicalComposer initialConfig={{editable: true}}>
...
</LexicalComposer>
```

After an editor is created, the mode can be changed imperatively:

```js
editor.setReadOnly(true);
editor.setEditable(true);
```

## Reading the mode

In order to find the current mode of the editor you can use:

```js
const readOnly = editor.isReadOnly(); // Returns true or false
const readOnly = editor.isEditable(); // Returns true or false
```

You can also get notified when the editor's read only mode has changed:

```js
const removeReadOnlyListener = editor.registerReadOnlyListener(
(readOnly) => {
// The editor's read only mode is passed in!
console.log(readOnly);
const removeEditableListener = editor.registerEditableListener(
(isEditable) => {
// The editor's mode is passed in!
console.log(isEditable);
},
);

// Do not forget to unregister the listener when no longer needed!
removeReadOnlyListener();
removeEditableListener();
```
12 changes: 6 additions & 6 deletions packages/lexical/flow/Lexical.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export type MutationListener = (
nodes: Map<NodeKey, NodeMutation>,
{updateTags: Set<string>, dirtyLeaves: Set<string>},
) => void;
export type ReadOnlyListener = (readOnly: boolean) => void;
export type EditableListener = (editable: boolean) => void;
type Listeners = {
decorator: Set<DecoratorListener>,
mutation: MutationListeners,
Expand Down Expand Up @@ -135,7 +135,7 @@ declare export class LexicalEditor {
_updateTags: Set<string>;
_observer: null | MutationObserver;
_key: string;
_readOnly: boolean;
_editable: boolean;
_headless: boolean;
isComposing(): boolean;
registerUpdateListener(listener: UpdateListener): () => void;
Expand All @@ -147,7 +147,7 @@ declare export class LexicalEditor {
listener: CommandListener<P>,
priority: CommandListenerPriority,
): () => void;
registerReadOnlyListener(listener: ReadOnlyListener): () => void;
registerEditableListener(listener: EditableListener): () => void;
registerMutationListener(
klass: Class<LexicalNode>,
listener: MutationListener,
Expand All @@ -174,8 +174,8 @@ declare export class LexicalEditor {
update(updateFn: () => void, options?: EditorUpdateOptions): boolean;
focus(callbackFn?: () => void, options?: EditorFocusOptions): void;
blur(): void;
isReadOnly(): boolean;
setReadOnly(readOnly: boolean): void;
isEditable(): boolean;
setEditable(editable: boolean): void;
toJSON(): SerializedEditor;
}
type EditorUpdateOptions = {
Expand Down Expand Up @@ -268,7 +268,7 @@ declare export function createEditor(editorConfig?: {
nodes?: $ReadOnlyArray<Class<LexicalNode>>,
onError: (error: Error) => void,
disableEvents?: boolean,
readOnly?: boolean,
editable?: boolean,
}): LexicalEditor;

/**
Expand Down
Loading