From 369f721bd803adadf8d329dc8ac5be295a9e33d7 Mon Sep 17 00:00:00 2001 From: ilia tapazukk Date: Sun, 26 Mar 2023 16:56:49 +0000 Subject: [PATCH] Add LinkForm component --- src/components/Editor/Editor.tsx | 3 - .../EditorBubbleMenu.module.scss | 35 -------- .../EditorBubbleMenu/EditorBubbleMenu.tsx | 56 +------------ .../LinkForm/LinkForm.module.scss | 46 ++++++++++ .../EditorBubbleMenu/LinkForm/LinkForm.tsx | 84 +++++++++++++++++++ .../Editor/EditorBubbleMenu/LinkForm/index.ts | 1 + src/components/Views/Create.module.scss | 4 + src/components/Views/Create.tsx | 4 +- 8 files changed, 139 insertions(+), 94 deletions(-) create mode 100644 src/components/Editor/EditorBubbleMenu/LinkForm/LinkForm.module.scss create mode 100644 src/components/Editor/EditorBubbleMenu/LinkForm/LinkForm.tsx create mode 100644 src/components/Editor/EditorBubbleMenu/LinkForm/index.ts diff --git a/src/components/Editor/Editor.tsx b/src/components/Editor/Editor.tsx index b3c06777..162feb24 100644 --- a/src/components/Editor/Editor.tsx +++ b/src/components/Editor/Editor.tsx @@ -1,12 +1,9 @@ import { createEffect } from 'solid-js' import { createTiptapEditor, useEditorHTML } from 'solid-tiptap' -import { clsx } from 'clsx' import { useLocalize } from '../../context/localize' import { Blockquote } from '@tiptap/extension-blockquote' import { Bold } from '@tiptap/extension-bold' import { BubbleMenu } from '@tiptap/extension-bubble-menu' -import * as Y from 'yjs' -import { WebrtcProvider } from 'y-webrtc' import { Dropcursor } from '@tiptap/extension-dropcursor' import { Italic } from '@tiptap/extension-italic' import { Strike } from '@tiptap/extension-strike' diff --git a/src/components/Editor/EditorBubbleMenu/EditorBubbleMenu.module.scss b/src/components/Editor/EditorBubbleMenu/EditorBubbleMenu.module.scss index 3b607f45..ced091f2 100644 --- a/src/components/Editor/EditorBubbleMenu/EditorBubbleMenu.module.scss +++ b/src/components/Editor/EditorBubbleMenu/EditorBubbleMenu.module.scss @@ -36,41 +36,6 @@ width: 1px; } - .linkForm { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - padding: 6px 11px; - - input { - margin: 0 12px 0 0; - padding: 0; - flex: 1; - border: none; - min-width: 200px; - - &:focus { - outline: none; - } - - &::placeholder { - color: rgba(#000, 0.3); - } - } - } - - .linkError { - padding: 6px 11px; - color: red; - font-size: 0.7em; - position: absolute; - bottom: -3rem; - left: 0; - right: 0; - background: #fff; - box-shadow: 0 4px 10px rgba(#000, 0.25); - } - .dropDownHolder { position: relative; cursor: pointer; diff --git a/src/components/Editor/EditorBubbleMenu/EditorBubbleMenu.tsx b/src/components/Editor/EditorBubbleMenu/EditorBubbleMenu.tsx index 8de91a56..0d86e74c 100644 --- a/src/components/Editor/EditorBubbleMenu/EditorBubbleMenu.tsx +++ b/src/components/Editor/EditorBubbleMenu/EditorBubbleMenu.tsx @@ -5,7 +5,7 @@ import { Icon } from '../../_shared/Icon' import { clsx } from 'clsx' import { createEditorTransaction } from 'solid-tiptap' import { useLocalize } from '../../../context/localize' -import validateUrl from '../../../utils/validateUrl' +import { LinkForm } from './LinkForm' type BubbleMenuProps = { editor: Editor @@ -38,44 +38,10 @@ export const EditorBubbleMenu = (props: BubbleMenuProps) => { const isBulletList = isActive('isBulletList') const isLink = isActive('link') - //TODO: вынести логику линки в отдельный компонент const toggleLinkForm = () => { - setLinkError(null) setLinkEditorOpen(true) } - const currentUrl = createEditorTransaction( - () => props.editor, - (editor) => { - return (editor && editor.getAttributes('link').href) || '' - } - ) - - const clearLinkForm = () => { - if (currentUrl()) { - props.editor.chain().focus().unsetLink().run() - } - setUrl('') - setLinkEditorOpen(false) - } - const handleUrlChange = (value) => { - setUrl(value) - } - const handleSubmitLink = () => { - if (validateUrl(url())) { - props.editor.chain().focus().setLink({ href: url() }).run() - setLinkEditorOpen(false) - } else { - setLinkError(t('Invalid url format')) - } - } - - const handleKeyPress = (event) => { - const key = event.key - if (key === 'Enter') handleSubmitLink() - if (key === 'Esc') clearLinkForm() - } - const toggleTextSizePopup = () => { if (listBubbleOpen()) setListBubbleOpen(false) setTextSizeBubbleOpen((prev) => !prev) @@ -90,25 +56,7 @@ export const EditorBubbleMenu = (props: BubbleMenuProps) => {
- <> -
- handleKeyPress(e)} - onChange={(e) => handleUrlChange(e.currentTarget.value)} - /> - - -
- {linkError() &&
{linkError()}
} - + setLinkEditorOpen(false)} />
<> diff --git a/src/components/Editor/EditorBubbleMenu/LinkForm/LinkForm.module.scss b/src/components/Editor/EditorBubbleMenu/LinkForm/LinkForm.module.scss new file mode 100644 index 00000000..402d0ad4 --- /dev/null +++ b/src/components/Editor/EditorBubbleMenu/LinkForm/LinkForm.module.scss @@ -0,0 +1,46 @@ +.LinkForm { + position: relative; + + .form { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + padding: 6px 11px; + + input { + margin: 0 12px 0 0; + padding: 0; + flex: 1; + border: none; + min-width: 200px; + display: block; + + &::placeholder { + color: rgba(#000, 0.3); + } + &:focus { + outline: none; + } + } + } + + .linkError { + padding: 6px 11px; + color: red; + font-size: 0.7em; + position: absolute; + bottom: -3rem; + left: 0; + right: 0; + height: 0; + background: #fff; + box-shadow: 0 4px 10px rgba(#000, 0.25); + opacity: 0; + transition: height 0.3s ease-in-out, opacity 0.3s ease-in-out; + + &.visible { + height: 32px; + opacity: 1; + } + } +} diff --git a/src/components/Editor/EditorBubbleMenu/LinkForm/LinkForm.tsx b/src/components/Editor/EditorBubbleMenu/LinkForm/LinkForm.tsx new file mode 100644 index 00000000..12b5c95c --- /dev/null +++ b/src/components/Editor/EditorBubbleMenu/LinkForm/LinkForm.tsx @@ -0,0 +1,84 @@ +import styles from './LinkForm.module.scss' +import { Icon } from '../../../_shared/Icon' +import { createEditorTransaction } from 'solid-tiptap' +import validateUrl from '../../../../utils/validateUrl' +import type { Editor } from '@tiptap/core' +import { createSignal } from 'solid-js' +import { useLocalize } from '../../../../context/localize' +import { clsx } from 'clsx' + +type Props = { + editor: Editor + onClose: () => void +} + +export const LinkForm = (props: Props) => { + const { t } = useLocalize() + const [url, setUrl] = createSignal('') + const [linkError, setLinkError] = createSignal('') + + const currentUrl = createEditorTransaction( + () => props.editor, + (editor) => { + return (editor && editor.getAttributes('link').href) || '' + } + ) + + const clearLinkForm = () => { + if (currentUrl()) { + props.editor.chain().focus().unsetLink().run() + } + setUrl('') + props.onClose() + } + + const handleUrlInput = (value) => { + setUrl(value) + } + + const handleSaveButtonClick = () => { + if (!validateUrl(url())) { + setLinkError(t('Invalid url format')) + return + } + + props.editor.chain().focus().setLink({ href: url() }).run() + props.onClose() + } + + const handleKeyPress = (event) => { + setLinkError('') + const key = event.key + + if (key === 'Enter') { + handleSaveButtonClick() + } + + if (key === 'Esc') { + clearLinkForm() + } + } + + return ( +
+
+ handleKeyPress(e)} + onInput={(e) => handleUrlInput(e.currentTarget.value)} + /> + + +
+ +
{linkError()}
+
+ ) +} diff --git a/src/components/Editor/EditorBubbleMenu/LinkForm/index.ts b/src/components/Editor/EditorBubbleMenu/LinkForm/index.ts new file mode 100644 index 00000000..43fe9b0d --- /dev/null +++ b/src/components/Editor/EditorBubbleMenu/LinkForm/index.ts @@ -0,0 +1 @@ +export { LinkForm } from './LinkForm' diff --git a/src/components/Views/Create.module.scss b/src/components/Views/Create.module.scss index 5db21e07..625fd8e1 100644 --- a/src/components/Views/Create.module.scss +++ b/src/components/Views/Create.module.scss @@ -4,6 +4,10 @@ padding: 1rem 1.2rem; } +.formHolder { + padding: 0 4rem; +} + .saveBlock { background: #f1f1f1; line-height: 1.4; diff --git a/src/components/Views/Create.tsx b/src/components/Views/Create.tsx index ce097e0c..ca834b80 100644 --- a/src/components/Views/Create.tsx +++ b/src/components/Views/Create.tsx @@ -53,7 +53,7 @@ export const CreateView = () => {
-
+

Slug

{ Выберите заглавное изображение для статьи, тут сразу можно увидеть как карточка будет выглядеть на главной странице

-
+