diff --git a/packages/slate-editor/src/components/SearchInput/Suggestions.tsx b/packages/slate-editor/src/components/SearchInput/Suggestions.tsx index 982a71260..de1310d52 100644 --- a/packages/slate-editor/src/components/SearchInput/Suggestions.tsx +++ b/packages/slate-editor/src/components/SearchInput/Suggestions.tsx @@ -25,7 +25,7 @@ export function Suggestions({ className, footer, minHeight = 200, - maxHeight = 1000, + maxHeight = 500, query, suggestions, ...attributes diff --git a/packages/slate-editor/src/extensions/placeholders/PlaceholderNode.ts b/packages/slate-editor/src/extensions/placeholders/PlaceholderNode.ts index f725a000a..a30d8b244 100644 --- a/packages/slate-editor/src/extensions/placeholders/PlaceholderNode.ts +++ b/packages/slate-editor/src/extensions/placeholders/PlaceholderNode.ts @@ -14,6 +14,7 @@ export namespace PlaceholderNode { export enum Type { ATTACHMENT = 'placeholder:attachment', CONTACT = 'placeholder:contact', + COVERAGE = 'placeholder:coverage', EMBED = 'placeholder:embed', GALLERY = 'placeholder:gallery', IMAGE = 'placeholder:image', diff --git a/packages/slate-editor/src/extensions/placeholders/PlaceholdersExtension.tsx b/packages/slate-editor/src/extensions/placeholders/PlaceholdersExtension.tsx index 0628ce470..bfe66e297 100644 --- a/packages/slate-editor/src/extensions/placeholders/PlaceholdersExtension.tsx +++ b/packages/slate-editor/src/extensions/placeholders/PlaceholdersExtension.tsx @@ -2,6 +2,7 @@ import type { NewsroomRef } from '@prezly/sdk'; import type { Extension } from '@prezly/slate-commons'; import React from 'react'; +import { CoveragePlaceholderElement } from './elements'; import { AttachmentPlaceholderElement, ContactPlaceholderElement, @@ -28,6 +29,12 @@ export interface Parameters { ContactPlaceholderElement.Props, 'getSuggestions' | 'renderEmpty' | 'renderSuggestion' | 'renderSuggestionsFooter' >; + withCoveragePlaceholders?: + | false + | Pick< + CoveragePlaceholderElement.Props, + 'getSuggestions' | 'renderEmpty' | 'renderSuggestion' | 'renderSuggestionsFooter' + >; withEmbedPlaceholders?: false | { fetchOembed: FetchOEmbedFn }; withGalleryPlaceholders?: boolean | { newsroom?: NewsroomRef }; withImagePlaceholders?: boolean | { withCaptions: boolean; newsroom?: NewsroomRef }; @@ -39,6 +46,7 @@ export interface Parameters { export function PlaceholdersExtension({ withAttachmentPlaceholders = false, withContactPlaceholders = false, + withCoveragePlaceholders = false, withEmbedPlaceholders = false, withGalleryPlaceholders = false, withImagePlaceholders = false, @@ -55,6 +63,7 @@ export function PlaceholdersExtension({ removeDisabledPlaceholders({ withAttachmentPlaceholders: Boolean(withAttachmentPlaceholders), withContactPlaceholders: Boolean(withContactPlaceholders), + withCoveragePlaceholders: Boolean(withCoveragePlaceholders), withEmbedPlaceholders: Boolean(withEmbedPlaceholders), withGalleryPlaceholders: Boolean(withGalleryPlaceholders), withImagePlaceholders: Boolean(withImagePlaceholders), @@ -88,6 +97,20 @@ export function PlaceholdersExtension({ ); } + if ( + withCoveragePlaceholders && + isPlaceholderNode(element, PlaceholderNode.Type.COVERAGE) + ) { + return ( + + {children} + + ); + } if (withEmbedPlaceholders && isPlaceholderNode(element, PlaceholderNode.Type.EMBED)) { return ( ; + +export function CoveragePlaceholderElement({ + children, + element, + getSuggestions, + renderEmpty, + renderSuggestion, + renderSuggestionsFooter, + ...props +}: CoveragePlaceholderElement.Props) { + const editor = useSlateStatic(); + + const handleTrigger = useFunction(() => { + PlaceholdersManager.activate(element); + }); + + const handleSelect = useFunction((data: CoverageRef) => { + EventsEditor.dispatchEvent(editor, 'coverage-dialog-submitted', { + coverage_id: data.coverage.id, + }); + + replacePlaceholder(editor, element, createCoverage(data.coverage.id)); + }); + + usePlaceholderManagement(element.type, element.uuid, { + onTrigger: handleTrigger, + }); + + return ( + + {...props} + element={element} + // Core + format="card" + icon={PlaceholderCoverage} + title="Click to insert coverage" + description="Add your Prezly coverage" + // Input + getSuggestions={getSuggestions} + renderEmpty={renderEmpty} + renderSuggestion={renderSuggestion} + renderSuggestions={(props) => ( + + {props.children} + + )} + inputTitle="Coverage" + inputDescription="Select coverage to insert" + inputPlaceholder="Search for coverage" + onSelect={handleSelect} + > + {children} + + ); +} + +export namespace CoveragePlaceholderElement { + export interface Props + extends Omit< + BaseProps, + | 'onSelect' + | 'icon' + | 'title' + | 'description' + | 'inputTitle' + | 'inputDescription' + | 'inputPlaceholder' + | 'renderSuggestions' + > { + element: PlaceholderNode; + renderSuggestionsFooter?: BaseProps['renderSuggestions']; + } +} diff --git a/packages/slate-editor/src/extensions/placeholders/elements/index.ts b/packages/slate-editor/src/extensions/placeholders/elements/index.ts index 8c19c08c1..2c8232cb0 100644 --- a/packages/slate-editor/src/extensions/placeholders/elements/index.ts +++ b/packages/slate-editor/src/extensions/placeholders/elements/index.ts @@ -1,5 +1,6 @@ export { AttachmentPlaceholderElement } from './AttachmentPlaceholderElement'; export { ContactPlaceholderElement } from './ContactPlaceholderElement'; +export { CoveragePlaceholderElement } from './CoveragePlaceholderElement'; export { EmbedPlaceholderElement } from './EmbedPlaceholderElement'; export { GalleryPlaceholderElement } from './GalleryPlaceholderElement'; export { ImagePlaceholderElement } from './ImagePlaceholderElement'; diff --git a/packages/slate-editor/src/extensions/placeholders/normalization/normalization.test.tsx b/packages/slate-editor/src/extensions/placeholders/normalization/normalization.test.tsx index 65e513584..ad0b94078 100644 --- a/packages/slate-editor/src/extensions/placeholders/normalization/normalization.test.tsx +++ b/packages/slate-editor/src/extensions/placeholders/normalization/normalization.test.tsx @@ -15,6 +15,7 @@ const normalizations = [ removeDisabledPlaceholders({ withAttachmentPlaceholders: Boolean('ENABLED'), withContactPlaceholders: false, + withCoveragePlaceholders: false, withEmbedPlaceholders: false, withGalleryPlaceholders: Boolean('ENABLED'), withImagePlaceholders: Boolean('ENABLED'), diff --git a/packages/slate-editor/src/extensions/placeholders/normalization/removeDisabledPlaceholders.ts b/packages/slate-editor/src/extensions/placeholders/normalization/removeDisabledPlaceholders.ts index 2ab2f97e3..6c16039d4 100644 --- a/packages/slate-editor/src/extensions/placeholders/normalization/removeDisabledPlaceholders.ts +++ b/packages/slate-editor/src/extensions/placeholders/normalization/removeDisabledPlaceholders.ts @@ -6,6 +6,7 @@ import { PlaceholderNode } from '../PlaceholderNode'; interface Parameters { withAttachmentPlaceholders: boolean; withContactPlaceholders: boolean; + withCoveragePlaceholders: boolean; withImagePlaceholders: boolean; withGalleryPlaceholders: boolean; withEmbedPlaceholders: boolean; @@ -17,6 +18,7 @@ interface Parameters { export function removeDisabledPlaceholders({ withAttachmentPlaceholders, withContactPlaceholders, + withCoveragePlaceholders, withImagePlaceholders, withGalleryPlaceholders, withEmbedPlaceholders, @@ -27,6 +29,7 @@ export function removeDisabledPlaceholders({ const config = { [PlaceholderNode.Type.ATTACHMENT]: withAttachmentPlaceholders, [PlaceholderNode.Type.CONTACT]: withContactPlaceholders, + [PlaceholderNode.Type.COVERAGE]: withCoveragePlaceholders, [PlaceholderNode.Type.IMAGE]: withImagePlaceholders, [PlaceholderNode.Type.GALLERY]: withGalleryPlaceholders, [PlaceholderNode.Type.EMBED]: withEmbedPlaceholders, diff --git a/packages/slate-editor/src/icons/Placeholder-Coverage.svg b/packages/slate-editor/src/icons/Placeholder-Coverage.svg new file mode 100644 index 000000000..b2b416284 --- /dev/null +++ b/packages/slate-editor/src/icons/Placeholder-Coverage.svg @@ -0,0 +1,5 @@ + + + diff --git a/packages/slate-editor/src/icons/Placeholder-Video.svg b/packages/slate-editor/src/icons/Placeholder-Video.svg index a3312a163..28d564f4c 100644 --- a/packages/slate-editor/src/icons/Placeholder-Video.svg +++ b/packages/slate-editor/src/icons/Placeholder-Video.svg @@ -1,3 +1,5 @@ - + diff --git a/packages/slate-editor/src/icons/Placeholder-WebBookmark.svg b/packages/slate-editor/src/icons/Placeholder-WebBookmark.svg index 21b296e6c..1414b543a 100644 --- a/packages/slate-editor/src/icons/Placeholder-WebBookmark.svg +++ b/packages/slate-editor/src/icons/Placeholder-WebBookmark.svg @@ -1,3 +1,5 @@ - + diff --git a/packages/slate-editor/src/icons/index.ts b/packages/slate-editor/src/icons/index.ts index 1f50bb7b5..d03252dd7 100644 --- a/packages/slate-editor/src/icons/index.ts +++ b/packages/slate-editor/src/icons/index.ts @@ -57,6 +57,7 @@ export { default as ItemsLayoutVertical } from './Items-Layout-Vertical.svg'; export { default as Link } from './Link.svg'; export { default as PlaceholderAttachment } from './Placeholder-Attachment.svg'; export { default as PlaceholderContact } from './Placeholder-Contact.svg'; +export { default as PlaceholderCoverage } from './Placeholder-Coverage.svg'; export { default as PlaceholderEmbed } from './Placeholder-Embed.svg'; export { default as PlaceholderImage } from './Placeholder-Image.svg'; export { default as PlaceholderGallery } from './Placeholder-Gallery.svg'; diff --git a/packages/slate-editor/src/modules/editor/Editor.tsx b/packages/slate-editor/src/modules/editor/Editor.tsx index 09517497c..b4df1ea80 100644 --- a/packages/slate-editor/src/modules/editor/Editor.tsx +++ b/packages/slate-editor/src/modules/editor/Editor.tsx @@ -372,6 +372,16 @@ export const Editor = forwardRef((props, forwardedRef) = return openFloatingPressContactsMenu(); } if (action === MenuAction.ADD_COVERAGE) { + if (withPlaceholders) { + const placeholder = insertPlaceholder( + editor, + { type: PlaceholderNode.Type.COVERAGE }, + true, + ); + PlaceholdersManager.trigger(placeholder); + EditorCommands.selectNode(editor, placeholder); + return; + } return openFloatingCoverageMenu(); } if (action === MenuAction.ADD_QUOTE) {