This commit is contained in:
Ilya Y 2023-07-28 22:53:21 +03:00 committed by GitHub
parent 844f65dd9d
commit ed5f34ac69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 37 deletions

View File

@ -1,6 +1,6 @@
import styles from './InlineForm.module.scss' import styles from './InlineForm.module.scss'
import { Icon } from '../../_shared/Icon' import { Icon } from '../../_shared/Icon'
import { createSignal } from 'solid-js' import { createSignal, onMount } from 'solid-js'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { Popover } from '../../_shared/Popover' import { Popover } from '../../_shared/Popover'
import { useLocalize } from '../../../context/localize' import { useLocalize } from '../../../context/localize'
@ -13,7 +13,6 @@ type Props = {
initialValue?: string initialValue?: string
showInput?: boolean showInput?: boolean
placeholder: string placeholder: string
autoFocus?: boolean
} }
export const InlineForm = (props: Props) => { export const InlineForm = (props: Props) => {
@ -21,6 +20,7 @@ export const InlineForm = (props: Props) => {
const [formValue, setFormValue] = createSignal(props.initialValue || '') const [formValue, setFormValue] = createSignal(props.initialValue || '')
const [formValueError, setFormValueError] = createSignal<string | undefined>() const [formValueError, setFormValueError] = createSignal<string | undefined>()
const inputRef: { current: HTMLInputElement } = { current: null }
const handleFormInput = (e) => { const handleFormInput = (e) => {
const value = e.currentTarget.value const value = e.currentTarget.value
setFormValueError() setFormValueError()
@ -57,11 +57,15 @@ export const InlineForm = (props: Props) => {
props.initialValue ? props.onClear() : props.onClose() props.initialValue ? props.onClear() : props.onClose()
} }
onMount(() => {
inputRef.current.focus()
})
return ( return (
<div class={styles.InlineForm}> <div class={styles.InlineForm}>
<div class={styles.form}> <div class={styles.form}>
<input <input
autofocus={props.autoFocus ?? true} ref={(el) => (inputRef.current = el)}
type="text" type="text"
value={props.initialValue ?? ''} value={props.initialValue ?? ''}
placeholder={props.placeholder} placeholder={props.placeholder}

View File

@ -1,12 +1,12 @@
import { Editor } from '@tiptap/core' import { Editor } from '@tiptap/core'
import { validateUrl } from '../../../utils/validateUrl' import { validateUrl } from '../../../utils/validateUrl'
import { hideModal } from '../../../stores/ui'
import { InlineForm } from '../InlineForm' import { InlineForm } from '../InlineForm'
import { useLocalize } from '../../../context/localize' import { useLocalize } from '../../../context/localize'
import { createEditorTransaction } from 'solid-tiptap' import { createEditorTransaction } from 'solid-tiptap'
type Props = { type Props = {
editor: Editor editor: Editor
onClose: () => void
} }
export const checkUrl = (url) => { export const checkUrl = (url) => {
@ -48,7 +48,7 @@ export const InsertLinkForm = (props: Props) => {
onClear={handleClearLinkForm} onClear={handleClearLinkForm}
validate={(value) => (validateUrl(value) ? '' : t('Invalid url format'))} validate={(value) => (validateUrl(value) ? '' : t('Invalid url format'))}
onSubmit={handleLinkFormSubmit} onSubmit={handleLinkFormSubmit}
onClose={() => hideModal()} onClose={() => props.onClose()}
/> />
</div> </div>
) )

View File

@ -138,6 +138,7 @@ const SimplifiedEditor = (props: Props) => {
} }
if (event.code === 'KeyK' && (event.metaKey || event.ctrlKey) && !editor().state.selection.empty) { if (event.code === 'KeyK' && (event.metaKey || event.ctrlKey) && !editor().state.selection.empty) {
event.preventDefault()
showModal('editorInsertLink') showModal('editorInsertLink')
} }
} }
@ -149,7 +150,7 @@ const SimplifiedEditor = (props: Props) => {
onCleanup(() => { onCleanup(() => {
window.removeEventListener('keydown', handleKeyDown) window.removeEventListener('keydown', handleKeyDown)
}) })
const handleToggleBlockquote = () => editor().chain().focus().toggleBlockquote().run()
const handleInsertLink = () => !editor().state.selection.empty && showModal('editorInsertLink') const handleInsertLink = () => !editor().state.selection.empty && showModal('editorInsertLink')
return ( return (
<div <div
@ -190,7 +191,7 @@ const SimplifiedEditor = (props: Props) => {
<button <button
ref={triggerRef} ref={triggerRef}
type="button" type="button"
onClick={() => handleInsertLink} onClick={handleInsertLink}
class={clsx(styles.actionButton, { [styles.active]: isLink() })} class={clsx(styles.actionButton, { [styles.active]: isLink() })}
> >
<Icon name="editor-link" /> <Icon name="editor-link" />
@ -203,7 +204,7 @@ const SimplifiedEditor = (props: Props) => {
<button <button
ref={triggerRef} ref={triggerRef}
type="button" type="button"
onClick={handleToggleBlockquote} onClick={() => editor().chain().focus().toggleBlockquote().run()}
class={clsx(styles.actionButton, { [styles.active]: isBlockquote() })} class={clsx(styles.actionButton, { [styles.active]: isBlockquote() })}
> >
<Icon name="editor-quote" /> <Icon name="editor-quote" />
@ -237,7 +238,7 @@ const SimplifiedEditor = (props: Props) => {
</div> </div>
</div> </div>
<Modal variant="narrow" name="editorInsertLink"> <Modal variant="narrow" name="editorInsertLink">
<InsertLinkForm editor={editor()} /> <InsertLinkForm editor={editor()} onClose={() => hideModal()} />
</Modal> </Modal>
<Show when={props.imageEnabled}> <Show when={props.imageEnabled}>
<Modal variant="narrow" name="uploadImage"> <Modal variant="narrow" name="uploadImage">

View File

@ -1,4 +1,4 @@
import { Switch, Match, createSignal, Show } from 'solid-js' import { Switch, Match, createSignal, Show, onMount, onCleanup } from 'solid-js'
import type { Editor } from '@tiptap/core' import type { Editor } from '@tiptap/core'
import styles from './TextBubbleMenu.module.scss' import styles from './TextBubbleMenu.module.scss'
import { Icon } from '../../_shared/Icon' import { Icon } from '../../_shared/Icon'
@ -51,12 +51,26 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
} }
setListBubbleOpen((prev) => !prev) setListBubbleOpen((prev) => !prev)
} }
const handleKeyDown = async (event) => {
if (event.code === 'KeyK' && (event.metaKey || event.ctrlKey) && !props.editor.state.selection.empty) {
event.preventDefault()
setLinkEditorOpen(true)
}
}
onMount(() => {
window.addEventListener('keydown', handleKeyDown)
})
onCleanup(() => {
window.removeEventListener('keydown', handleKeyDown)
})
return ( return (
<div ref={props.ref} class={styles.TextBubbleMenu}> <div ref={props.ref} class={styles.TextBubbleMenu}>
<Switch> <Switch>
<Match when={linkEditorOpen()}> <Match when={linkEditorOpen()}>
<InsertLinkForm editor={props.editor} /> <InsertLinkForm editor={props.editor} onClose={() => setLinkEditorOpen(false)} />
</Match> </Match>
<Match when={!linkEditorOpen()}> <Match when={!linkEditorOpen()}>
<> <>

View File

@ -106,7 +106,6 @@ export const UploadModalContent = (props: Props) => {
</Show> </Show>
<div class={styles.formHolder}> <div class={styles.formHolder}>
<InlineForm <InlineForm
autoFocus={false}
placeholder={t('Or paste a link to an image')} placeholder={t('Or paste a link to an image')}
showInput={true} showInput={true}
onClose={() => { onClose={() => {

View File

@ -304,29 +304,31 @@ export const SolidSwiper = (props: Props) => {
</div> </div>
} }
> >
<div class={styles.description}> <Show when={props.images.length > 0}>
<input <div class={styles.description}>
type="text" <input
class={clsx(styles.input, styles.title)} type="text"
placeholder={t('Enter image title')} class={clsx(styles.input, styles.title)}
value={props.images[slideIndex()].title} placeholder={t('Enter image title')}
onChange={(event) => handleSlideDescriptionChange(slideIndex(), 'title', event.target.value)} value={props.images[slideIndex()].title}
/> onChange={(event) => handleSlideDescriptionChange(slideIndex(), 'title', event.target.value)}
<input />
type="text" <input
class={styles.input} type="text"
placeholder={t('Specify the source and the name of the author')} class={styles.input}
value={props.images[slideIndex()].source} placeholder={t('Specify the source and the name of the author')}
onChange={(event) => handleSlideDescriptionChange(slideIndex(), 'source', event.target.value)} value={props.images[slideIndex()].source}
/> onChange={(event) => handleSlideDescriptionChange(slideIndex(), 'source', event.target.value)}
<SimplifiedEditor />
initialContent={props.images[slideIndex()].body} <SimplifiedEditor
smallHeight={true} initialContent={props.images[slideIndex()].body}
placeholder={t('Enter image description')} smallHeight={true}
onSubmit={(value) => handleSlideDescriptionChange(slideIndex(), 'body', value)} placeholder={t('Enter image description')}
submitButtonText={t('Save')} onSubmit={(value) => handleSlideDescriptionChange(slideIndex(), 'body', value)}
/> submitButtonText={t('Save')}
</div> />
</div>
</Show>
</Show> </Show>
</div> </div>
) )

View File

@ -30,10 +30,10 @@ export const CreatePage = () => {
</div> </div>
</li> </li>
<li> <li>
<a href="#"> <div class={styles.link} onClick={() => handleCreate('literature')}>
<Icon name="create-books" class={styles.icon} /> <Icon name="create-books" class={styles.icon} />
<div>{t('literature')}</div> <div>{t('literature')}</div>
</a> </div>
</li> </li>
<li> <li>
<div class={styles.link} onClick={() => handleCreate('image')}> <div class={styles.link} onClick={() => handleCreate('image')}>