Skip to content

Commit

Permalink
[CARE-1802] Finish transitioning of SnippetsExtension to be self-suff…
Browse files Browse the repository at this point in the history
…icient UI component

Related to 7425e75
  • Loading branch information
e1himself committed Sep 18, 2023
1 parent 9423838 commit e71b889
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 82 deletions.
43 changes: 20 additions & 23 deletions packages/slate-commons/src/lib/useSavedSelection.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
import { useState } from 'react';
import { useMemo, useState } from 'react';
import type { BaseEditor, Editor } from 'slate';
import { ReactEditor } from 'slate-react';

import { saveSelection } from '../commands';

type SavedSelection = ReturnType<typeof saveSelection>;

interface Actions {
restore: (editor: ReactEditor & Editor, options?: { focus?: boolean }) => void;
save: (editor: Editor) => void;
}

export function useSavedSelection(): Actions {
export function useSavedSelection() {
const [savedSelection, setSavedSelection] = useState<SavedSelection | null>(null);

function restore(editor: ReactEditor & Editor, { focus = false } = {}) {
if (focus) {
ReactEditor.focus(editor);
}

if (savedSelection) {
savedSelection.restore(editor);
setSavedSelection(null);
}
}

function save(editor: BaseEditor) {
return setSavedSelection(saveSelection(editor));
}

return { restore, save };
return useMemo(
() => ({
restore(editor: ReactEditor & Editor, { focus = false } = {}) {
if (focus) {
ReactEditor.focus(editor);
}

if (savedSelection) {
savedSelection.restore(editor);
setSavedSelection(null);
}
},
save(editor: BaseEditor) {
return setSavedSelection(saveSelection(editor));
},
}),
[savedSelection],
);
}
70 changes: 45 additions & 25 deletions packages/slate-editor/src/extensions/snippet/SnippetsExtension.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useRegisterExtension } from '@prezly/slate-commons';
import React from 'react';
import type { RefObject } from 'react';
import React, { forwardRef, useImperativeHandle } from 'react';

import { FloatingSnippetInput } from './components';
import { useFloatingSnippetInput } from './lib';
Expand All @@ -9,30 +10,49 @@ export const EXTENSION_ID = 'SnippetsExtension';

export interface Parameters extends SnippetsExtensionConfiguration {
availableWidth: number;
containerRef: RefObject<HTMLDivElement>;
}

export function SnippetsExtension({ availableWidth, renderInput }: Parameters) {
const [{ isOpen }, { close, open, rootClose, submit }] = useFloatingSnippetInput();

useRegisterExtension({
id: EXTENSION_ID,
});

return (
<>
{isOpen && (
<FloatingSnippetInput
availableWidth={availableWidth}
containerRef={containerRef}
onClose={close}
onRootClose={rootClose}
renderInput={() =>
renderInput({
onCreate: submit,
})
}
/>
)}
</>
);
export const SnippetsExtension = forwardRef(
({ availableWidth, containerRef, renderInput }: Parameters, forwardedRef) => {
const { isOpen, close, open, rootClose, submit } = useFloatingSnippetInput();

useImperativeHandle(
forwardedRef,
(): SnippetsExtension.Ref => ({
open,
}),
[open],
);

useRegisterExtension({
id: EXTENSION_ID,
});

return (
<>
{isOpen && (
<FloatingSnippetInput
availableWidth={availableWidth}
containerRef={containerRef}
onClose={close}
onRootClose={rootClose}
renderInput={() =>
renderInput({
onCreate: submit,
})
}
/>
)}
</>
);
},
);

SnippetsExtension.displayName = 'SnippetsExtension';

export namespace SnippetsExtension {
export interface Ref {
open(): void;
}
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
import { EditorCommands, useSavedSelection } from '@prezly/slate-commons';
import type { DocumentNode } from '@prezly/slate-types';
import { useState } from 'react';
import type { Editor } from 'slate';
import { useCallback, useState } from 'react';
import { useSlateStatic } from 'slate-react';

import { EventsEditor } from '#modules/events';

interface State {
isOpen: boolean;
}

interface Actions {
close: () => void;
open: () => void;
rootClose: () => void;
submit: (node: DocumentNode) => Promise<void>;
}

export function useFloatingSnippetInput(editor: Editor): [State, Actions] {
export function useFloatingSnippetInput() {
const editor = useSlateStatic();
const [isOpen, setIsOpen] = useState<boolean>(false);
const savedSelection = useSavedSelection();

function close() {
const open = useCallback(() => {
EventsEditor.dispatchEvent(editor, 'snippet-dialog-opened');
setIsOpen(true);
savedSelection.save(editor);
}, [editor, savedSelection]);

const close = useCallback(() => {
savedSelection.restore(editor, { focus: true });
setIsOpen(false);
}
}, [editor, savedSelection]);

function rootClose() {
const rootClose = useCallback(() => {
setIsOpen(false);
}

function open() {
EventsEditor.dispatchEvent(editor, 'snippet-dialog-opened');
setIsOpen(true);
savedSelection.save(editor);
}
}, []);

async function submit(node: DocumentNode) {
EventsEditor.dispatchEvent(editor, 'snippet-dialog-submitted');
Expand All @@ -58,5 +48,5 @@ export function useFloatingSnippetInput(editor: Editor): [State, Actions] {
}
}

return [{ isOpen }, { close, open, rootClose, submit }];
return { isOpen, close, open, rootClose, submit };
}
15 changes: 13 additions & 2 deletions packages/slate-editor/src/modules/editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { FlashNodesExtension } from '#extensions/flash-nodes';
import { FloatingAddMenuExtension, type Option } from '#extensions/floating-add-menu';
import { insertPlaceholder, PlaceholderNode } from '#extensions/placeholders';
import { RichFormattingMenuExtension, toggleBlock } from '#extensions/rich-formatting-menu';
import { SnippetsExtension } from '#extensions/snippet';
import { Placeholder } from '#modules/components';
import { DecorationsProvider } from '#modules/decorations';
import { EditableWithExtensions } from '#modules/editable';
Expand Down Expand Up @@ -223,6 +224,8 @@ export const Editor = forwardRef<EditorRef, EditorProps>((props, forwardedRef) =
}),
);

const snippetsExtension = useRef<SnippetsExtension.Ref>();

const withSpecificProviderOptions =
typeof withFloatingAddMenu === 'object'
? withFloatingAddMenu.withSpecificProviderOptions
Expand Down Expand Up @@ -588,7 +591,7 @@ export const Editor = forwardRef<EditorRef, EditorProps>((props, forwardedRef) =
return;
}
if (action === MenuAction.ADD_SNIPPET) {
// return openFloatingSnippetInput(); // FIXME: Find a way to trigger snippet input
snippetsExtension.current?.open();
}
if (action === MenuAction.ADD_GALLERY && withGalleries) {
const placeholder = insertPlaceholder(
Expand Down Expand Up @@ -746,7 +749,6 @@ export const Editor = forwardRef<EditorRef, EditorProps>((props, forwardedRef) =
withLists={withLists}
withPlaceholders={withPlaceholders}
withPressContacts={withPressContacts}
withSnippets={withSnippets}
withStoryBookmarks={withStoryBookmarks}
withStoryEmbeds={withStoryEmbeds}
withTables={withTables}
Expand All @@ -765,6 +767,15 @@ export const Editor = forwardRef<EditorRef, EditorProps>((props, forwardedRef) =
</Placeholder>
)}

{withSnippets && (
<SnippetsExtension
ref={snippetsExtension}
{...withSnippets}
availableWidth={availableWidth}
containerRef={containerRef}
/>
)}

{withFloatingAddMenu && (
<FloatingAddMenuExtension<MenuAction>
tooltip={
Expand Down
7 changes: 0 additions & 7 deletions packages/slate-editor/src/modules/editor/Extensions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { createParagraph, ParagraphsExtension } from '#extensions/paragraphs';
import { PasteSlateContentExtension } from '#extensions/paste-slate-content';
import { PlaceholdersExtension } from '#extensions/placeholders';
import { PressContactsExtension } from '#extensions/press-contacts';
import { SnippetsExtension } from '#extensions/snippet';
import { SoftBreakExtension } from '#extensions/soft-break';
import { StoryBookmarkExtension } from '#extensions/story-bookmark';
import { StoryEmbedExtension } from '#extensions/story-embed';
Expand Down Expand Up @@ -88,7 +87,6 @@ type Props = {
| 'withWebBookmarks'
| 'withStoryEmbeds'
| 'withStoryBookmarks'
| 'withSnippets'
>;

export function Extensions({
Expand All @@ -112,7 +110,6 @@ export function Extensions({
withLists,
withPlaceholders,
withPressContacts,
withSnippets,
withStoryBookmarks,
withStoryEmbeds,
withTables,
Expand Down Expand Up @@ -261,10 +258,6 @@ export function Extensions({
withWebBookmarkPlaceholders={withWebBookmarks}
/>

{withSnippets && (
<SnippetsExtension availableWidth={availableWidth} {...withSnippets} />
)}

{withStoryEmbeds && <StoryEmbedExtension {...withStoryEmbeds} />}

{withStoryBookmarks && <StoryBookmarkExtension {...withStoryBookmarks} />}
Expand Down

0 comments on commit e71b889

Please sign in to comment.