Files
linsa-linsa-io/web/components/la-editor/la-editor.tsx
Aslam 867478d55c fix: Link, Pages, Topic, Hook and Others (#178)
* chore: remove useKeyDownListener

* chore: remove react-use, update jazz version and add query string

* chore: update jazz version

* chore: use simple mac or win utils code

* feat(util): add isTextInput

* feat(hooks): all needed hooks

* fix: link bunch stuff

* fix: page bunch stuff

* chore: bunch update for custom component

* chore: use throttle from internal hook

* chore: topic bunch stuff

* chore: update layout

* fix: truncate content header of topic detail
2024-09-23 23:16:02 +07:00

100 lines
2.3 KiB
TypeScript

import * as React from "react"
import { EditorContent, useEditor } from "@tiptap/react"
import { Editor, Content } from "@tiptap/core"
import { BubbleMenu } from "./components/bubble-menu"
import { createExtensions } from "./extensions"
import "./styles/index.css"
import { cn } from "@/lib/utils"
import { getOutput } from "./lib/utils"
import type { EditorView } from "@tiptap/pm/view"
import { useThrottle } from "@/hooks/use-throttle"
export interface LAEditorProps extends Omit<React.HTMLProps<HTMLDivElement>, "value"> {
output?: "html" | "json" | "text"
placeholder?: string
editorClassName?: string
onUpdate?: (content: Content) => void
onBlur?: (content: Content) => void
onNewBlock?: (content: Content) => void
handleKeyDown?: (view: EditorView, event: KeyboardEvent) => boolean
value?: any
throttleDelay?: number
}
export interface LAEditorRef {
editor: Editor | null
}
export const LAEditor = React.forwardRef<LAEditorRef, LAEditorProps>(
(
{
value,
placeholder,
output = "html",
editorClassName,
className,
onUpdate,
onBlur,
onNewBlock,
handleKeyDown,
throttleDelay = 1000,
...props
},
ref
) => {
const throttledSetValue = useThrottle((value: Content) => onUpdate?.(value), throttleDelay)
const handleUpdate = React.useCallback(
(editor: Editor) => {
throttledSetValue(getOutput(editor, output))
},
[output, throttledSetValue]
)
const editor = useEditor({
autofocus: false,
immediatelyRender: false,
extensions: createExtensions({ placeholder }),
editorProps: {
attributes: {
autocomplete: "off",
autocorrect: "off",
autocapitalize: "off",
class: editorClassName || ""
},
handleKeyDown
},
onCreate: ({ editor }) => {
editor.commands.setContent(value)
},
onUpdate: ({ editor }) => handleUpdate(editor),
onBlur: ({ editor }) => {
onBlur?.(getOutput(editor, output))
}
})
React.useImperativeHandle(
ref,
() => ({
editor: editor
}),
[editor]
)
if (!editor) {
return null
}
return (
<div className={cn("la-editor relative flex h-full w-full grow flex-col", className)} {...props}>
<EditorContent editor={editor} />
<BubbleMenu editor={editor} />
</div>
)
}
)
LAEditor.displayName = "LAEditor"
export default LAEditor