From 316c8b62a3ab17bc6b3b8eb4019194befb441545 Mon Sep 17 00:00:00 2001 From: Daniel Lautzenheiser Date: Thu, 31 Aug 2023 14:00:14 -0400 Subject: [PATCH] fix: insert link for selected text behavior (#858) --- .../src/components/common/button/Button.tsx | 4 +- .../buttons/InsertLinkToolbarButton.tsx | 46 +++++++++---------- .../plate/components/common/MediaPopover.tsx | 7 ++- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/packages/core/src/components/common/button/Button.tsx b/packages/core/src/components/common/button/Button.tsx index f73c9cf5..096d4b98 100644 --- a/packages/core/src/components/common/button/Button.tsx +++ b/packages/core/src/components/common/button/Button.tsx @@ -18,10 +18,10 @@ export interface BaseBaseProps { endIcon?: FC<{ className?: string }>; title?: string; 'data-testid'?: string; + onClick?: MouseEventHandler; } export interface ButtonProps extends BaseBaseProps { - onClick?: MouseEventHandler; disabled?: boolean; buttonRef?: Ref; 'aria-label'?: string; @@ -81,6 +81,7 @@ const Button: FC = ({ title={title} data-testid={dataTestId} className={buttonClassNames} + onClick={otherProps.onClick} style={style} > {content} @@ -96,6 +97,7 @@ const Button: FC = ({ title={title} data-testid={dataTestId} className={buttonClassNames} + onClick={otherProps.onClick} style={style} target="_blank" rel="noreferrer" diff --git a/packages/core/src/widgets/markdown/plate/components/buttons/InsertLinkToolbarButton.tsx b/packages/core/src/widgets/markdown/plate/components/buttons/InsertLinkToolbarButton.tsx index 269e1cb1..18fe569e 100644 --- a/packages/core/src/widgets/markdown/plate/components/buttons/InsertLinkToolbarButton.tsx +++ b/packages/core/src/widgets/markdown/plate/components/buttons/InsertLinkToolbarButton.tsx @@ -1,6 +1,7 @@ import { Link as LinkIcon } from '@styled-icons/material/Link'; import { ELEMENT_LINK, + deleteText, getEditorString, getNode, getSelectionText, @@ -9,7 +10,7 @@ import { setNodes, someNode, } from '@udecode/plate'; -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useMemo } from 'react'; import useMediaInsert from '@staticcms/core/lib/hooks/useMediaInsert'; import useUUID from '@staticcms/core/lib/hooks/useUUID'; @@ -21,7 +22,7 @@ import type { Collection, MarkdownField, MediaPath } from '@staticcms/core/inter import type { MdLinkElement } from '@staticcms/markdown/plate/plateTypes'; import type { TText } from '@udecode/plate'; import type { FC } from 'react'; -import type { Path } from 'slate'; +import type { Location } from 'slate'; export interface InsertLinkToolbarButtonProps { variant: 'button' | 'menu'; @@ -38,25 +39,25 @@ const InsertLinkToolbarButton: FC = ({ currentValue, disabled, }) => { - const [selection, setSelection] = useState(); const editor = useMdPlateEditorState(); const handleInsert = useCallback( ({ path: newUrl, alt: newText }: MediaPath) => { - if (isNotEmpty(newUrl) && selection) { + const selectionPoint = editor.selection?.focus.path; + if (isNotEmpty(newUrl) && selectionPoint) { const text = isNotEmpty(newText) ? newText : newUrl; - const linkAt = getNode(editor, selection); + const linkAt = getNode(editor, selectionPoint); if (linkAt && linkAt.type === ELEMENT_LINK) { if (newUrl !== linkAt.url || text !== linkAt.children[0].text) { setNodes( editor, { url: newUrl, children: [{ text: newText }] }, - { at: selection }, + { at: selectionPoint }, ); - if (text !== getEditorString(editor, selection)) { + if (text !== getEditorString(editor, selectionPoint)) { replaceNodeChildren(editor, { - at: selection, + at: selectionPoint, nodes: { text }, insertOptions: { select: true, @@ -68,32 +69,29 @@ const InsertLinkToolbarButton: FC = ({ return; } + console.log('editor.selection', editor.selection); + + deleteText(editor, { + at: editor.selection as unknown as Location, + }); + insertLink( editor, { url: newUrl, text }, { - at: selection, + at: editor.selection as unknown as Location, }, ); - const newSelection = [...selection]; - const lastIndex = newSelection.pop() ?? 0; - setSelection([...newSelection, lastIndex + 1]); } }, - [editor, selection], + [editor], ); const chooseUrl = useMemo(() => field.choose_url ?? true, [field.choose_url]); const isLink = !!editor?.selection && someNode(editor, { match: { type: ELEMENT_LINK } }); - const selectedText: string = useMemo(() => { - if (!editor.selection) { - return ''; - } - - return getSelectionText(editor); - }, [editor]); + const selectedText = !editor.selection ? '' : getSelectionText(editor); const controlID = useUUID(); const openMediaLibrary = useMediaInsert( @@ -106,21 +104,19 @@ const InsertLinkToolbarButton: FC = ({ ); const handleOpenMediaLibrary = useCallback(() => { - setSelection(editor.selection?.focus.path); openMediaLibrary(); - }, [editor.selection, openMediaLibrary]); + }, [openMediaLibrary]); - return ( + return !isLink ? ( - ); + ) : null; }; export default InsertLinkToolbarButton; diff --git a/packages/core/src/widgets/markdown/plate/components/common/MediaPopover.tsx b/packages/core/src/widgets/markdown/plate/components/common/MediaPopover.tsx index c9d6b78f..75dae460 100644 --- a/packages/core/src/widgets/markdown/plate/components/common/MediaPopover.tsx +++ b/packages/core/src/widgets/markdown/plate/components/common/MediaPopover.tsx @@ -13,6 +13,7 @@ import type { MarkdownField, MediaPath, } from '@staticcms/core/interface'; +import type { MouseEvent } from 'react'; export interface MediaPopoverProps { anchorEl: HTMLElement | null; @@ -69,6 +70,10 @@ const MediaPopover = ({ handleMediaChange, ); + const noop = useCallback((event: MouseEvent) => { + event.stopPropagation(); + }, []); + const open = Boolean(anchorEl); const id = open ? 'edit-popover' : undefined; @@ -122,7 +127,7 @@ const MediaPopover = ({ " /> {!forImage ? ( - ) : null}