Skip to content

Commit

Permalink
Change read only mode API to editable mode (#2912)
Browse files Browse the repository at this point in the history
* Remove read only mode API, make dit mode

* Fix docs

* Fixes
  • Loading branch information
trueadm authored and thegreatercurve committed Nov 25, 2022
1 parent 3ac2059 commit 2c16e30
Show file tree
Hide file tree
Showing 15 changed files with 101 additions and 102 deletions.
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 @@ -269,7 +269,7 @@ declare export function createEditor(editorConfig?: {
nodes?: $ReadOnlyArray<Class<LexicalNode>>,
onError: (error: Error) => void,
disableEvents?: boolean,
readOnly?: boolean,
editable?: boolean,
}): LexicalEditor;

/**
Expand Down
Loading

0 comments on commit 2c16e30

Please sign in to comment.