2022-11-10 12:50:47 +00:00
|
|
|
|
import { For, createEffect, createSignal, onCleanup, onMount } from 'solid-js'
|
2022-11-09 17:57:35 +00:00
|
|
|
|
import type { JSX } from 'solid-js'
|
|
|
|
|
import { undo, redo } from 'prosemirror-history'
|
|
|
|
|
import { clsx } from 'clsx'
|
|
|
|
|
import styles from './Sidebar.module.scss'
|
|
|
|
|
import { useOutsideClickHandler } from '../../utils/useOutsideClickHandler'
|
|
|
|
|
import { useEscKeyDownHandler } from '../../utils/useEscKeyDownHandler'
|
|
|
|
|
import type { EditorView } from 'prosemirror-view'
|
|
|
|
|
|
|
|
|
|
const Off = (props) => <div class={styles.sidebarOff}>{props.children}</div>
|
|
|
|
|
|
|
|
|
|
const Link = (props: {
|
|
|
|
|
disabled?: boolean
|
|
|
|
|
title?: string
|
|
|
|
|
className?: string
|
|
|
|
|
children: JSX.Element
|
|
|
|
|
onClick?: () => void
|
|
|
|
|
}) => (
|
|
|
|
|
<button
|
2023-02-17 09:21:02 +00:00
|
|
|
|
class={clsx(styles.sidebarLink, props.className)}
|
2022-11-09 17:57:35 +00:00
|
|
|
|
onClick={props.onClick}
|
|
|
|
|
disabled={props.disabled}
|
|
|
|
|
title={props.title}
|
|
|
|
|
data-testid={props['data-testid']}
|
|
|
|
|
>
|
|
|
|
|
{props.children}
|
|
|
|
|
</button>
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const Keys = (props: { keys: string[] }) => (
|
|
|
|
|
<span>
|
|
|
|
|
<For each={props.keys}>{(k) => <i>{k}</i>}</For>
|
|
|
|
|
</span>
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type SidebarProps = {
|
|
|
|
|
editorViewRef: {
|
|
|
|
|
current: EditorView
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const Sidebar = (props: SidebarProps) => {
|
|
|
|
|
const [lastAction, setLastAction] = createSignal<string | undefined>()
|
|
|
|
|
|
|
|
|
|
const { editorViewRef } = props
|
|
|
|
|
|
|
|
|
|
const onUndo = () => undo(editorViewRef.current.state, editorViewRef.current.dispatch)
|
|
|
|
|
const onRedo = () => redo(editorViewRef.current.state, editorViewRef.current.dispatch)
|
|
|
|
|
|
|
|
|
|
const [isHidden, setIsHidden] = createSignal(true)
|
|
|
|
|
|
|
|
|
|
const toggleSidebar = () => {
|
|
|
|
|
setIsHidden((oldIsHidden) => !oldIsHidden)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createEffect(() => {
|
|
|
|
|
setLastAction()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
createEffect(() => {
|
|
|
|
|
if (!lastAction()) return
|
|
|
|
|
const id = setTimeout(() => {
|
|
|
|
|
setLastAction()
|
|
|
|
|
}, 1000)
|
|
|
|
|
onCleanup(() => clearTimeout(id))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const [mod, setMod] = createSignal<'Ctrl' | 'Cmd'>('Ctrl')
|
|
|
|
|
|
|
|
|
|
onMount(() => {
|
|
|
|
|
setMod(navigator.platform.includes('Mac') ? 'Cmd' : 'Ctrl')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const containerRef: { current: HTMLElement } = {
|
|
|
|
|
current: null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
useEscKeyDownHandler(() => setIsHidden(true))
|
|
|
|
|
useOutsideClickHandler({
|
|
|
|
|
containerRef,
|
|
|
|
|
predicate: () => !isHidden(),
|
|
|
|
|
handler: () => setIsHidden(true)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
class={clsx(styles.sidebarContainer, {
|
|
|
|
|
[styles.sidebarContainerHidden]: isHidden()
|
|
|
|
|
})}
|
|
|
|
|
ref={(el) => (containerRef.current = el)}
|
|
|
|
|
>
|
|
|
|
|
<span class={styles.sidebarOpener} onClick={toggleSidebar}>
|
|
|
|
|
Советы и предложения
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<Off onClick={() => editorViewRef.current.focus()}>
|
|
|
|
|
<div class={styles.sidebarCloser} onClick={toggleSidebar} />
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<Link onClick={onUndo}>
|
|
|
|
|
Undo <Keys keys={[mod(), 'z']} />
|
|
|
|
|
</Link>
|
|
|
|
|
<Link onClick={onRedo}>
|
|
|
|
|
Redo <Keys keys={[mod(), 'Shift', 'z']} />
|
|
|
|
|
</Link>
|
|
|
|
|
</div>
|
|
|
|
|
</Off>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|