95 lines
2.5 KiB
TypeScript
95 lines
2.5 KiB
TypeScript
|
|
import { useEffect, useMemo, useState } from "react"
|
||
|
|
import type { ComponentProps, ReactNode } from "react"
|
||
|
|
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext"
|
||
|
|
import { mergeRegister } from "@lexical/utils"
|
||
|
|
import {
|
||
|
|
CAN_REDO_COMMAND,
|
||
|
|
CAN_UNDO_COMMAND,
|
||
|
|
COMMAND_PRIORITY_LOW,
|
||
|
|
SELECTION_CHANGE_COMMAND,
|
||
|
|
} from "lexical"
|
||
|
|
import { TooltipProvider } from "@workspace/ui/components/tooltip"
|
||
|
|
import { cn } from "@workspace/ui/lib/utils"
|
||
|
|
|
||
|
|
import { defaultActionState, LexicalActionContext } from "./context"
|
||
|
|
import { LexicalActionTree } from "./actions-view"
|
||
|
|
import { useLexicalActions } from "./actions-context"
|
||
|
|
|
||
|
|
export type LexicalFixedToolbarProps = ComponentProps<"div">
|
||
|
|
|
||
|
|
function LexicalActionRuntimeProvider({ children }: { children: ReactNode }) {
|
||
|
|
const [editor] = useLexicalComposerContext()
|
||
|
|
const [state, setState] = useState(defaultActionState)
|
||
|
|
const context = useMemo(() => ({ editor, state }), [editor, state])
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
const update = () => {
|
||
|
|
setState((current) => ({
|
||
|
|
...current,
|
||
|
|
revision: current.revision + 1,
|
||
|
|
}))
|
||
|
|
}
|
||
|
|
return mergeRegister(
|
||
|
|
editor.registerUpdateListener(update),
|
||
|
|
editor.registerCommand(
|
||
|
|
SELECTION_CHANGE_COMMAND,
|
||
|
|
() => {
|
||
|
|
update()
|
||
|
|
return false
|
||
|
|
},
|
||
|
|
COMMAND_PRIORITY_LOW
|
||
|
|
),
|
||
|
|
editor.registerCommand(
|
||
|
|
CAN_UNDO_COMMAND,
|
||
|
|
(canUndo) => {
|
||
|
|
setState((current) => ({ ...current, canUndo }))
|
||
|
|
return false
|
||
|
|
},
|
||
|
|
COMMAND_PRIORITY_LOW
|
||
|
|
),
|
||
|
|
editor.registerCommand(
|
||
|
|
CAN_REDO_COMMAND,
|
||
|
|
(canRedo) => {
|
||
|
|
setState((current) => ({ ...current, canRedo }))
|
||
|
|
return false
|
||
|
|
},
|
||
|
|
COMMAND_PRIORITY_LOW
|
||
|
|
)
|
||
|
|
)
|
||
|
|
}, [editor])
|
||
|
|
|
||
|
|
return (
|
||
|
|
<LexicalActionContext.Provider value={context}>
|
||
|
|
<TooltipProvider>{children}</TooltipProvider>
|
||
|
|
</LexicalActionContext.Provider>
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
export function LexicalFixedToolbar({
|
||
|
|
className,
|
||
|
|
children,
|
||
|
|
...props
|
||
|
|
}: LexicalFixedToolbarProps) {
|
||
|
|
const actions = useLexicalActions("toolbar")
|
||
|
|
|
||
|
|
if (actions.length === 0 && children == null) return null
|
||
|
|
|
||
|
|
return (
|
||
|
|
<LexicalActionRuntimeProvider>
|
||
|
|
<div
|
||
|
|
role="toolbar"
|
||
|
|
className={cn(
|
||
|
|
"flex min-h-11 flex-wrap items-center gap-1 border-b p-1",
|
||
|
|
className
|
||
|
|
)}
|
||
|
|
{...props}
|
||
|
|
>
|
||
|
|
<LexicalActionTree items={actions} />
|
||
|
|
{children}
|
||
|
|
</div>
|
||
|
|
</LexicalActionRuntimeProvider>
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
export { LexicalActionRuntimeProvider }
|