| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 | 
							- import {
 -   useCallback,
 -   useEffect,
 -   useRef,
 -   useState,
 - } from 'react'
 - import type { Dispatch, RefObject, SetStateAction } from 'react'
 - import type {
 -   Klass,
 -   LexicalCommand,
 -   LexicalEditor,
 -   TextNode,
 - } from 'lexical'
 - import {
 -   $getNodeByKey,
 -   $getSelection,
 -   $isDecoratorNode,
 -   $isNodeSelection,
 -   COMMAND_PRIORITY_LOW,
 -   KEY_BACKSPACE_COMMAND,
 -   KEY_DELETE_COMMAND,
 - } from 'lexical'
 - import type { EntityMatch } from '@lexical/text'
 - import {
 -   mergeRegister,
 - } from '@lexical/utils'
 - import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection'
 - import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
 - import { $isContextBlockNode } from './plugins/context-block/node'
 - import { DELETE_CONTEXT_BLOCK_COMMAND } from './plugins/context-block'
 - import { $isHistoryBlockNode } from './plugins/history-block/node'
 - import { DELETE_HISTORY_BLOCK_COMMAND } from './plugins/history-block'
 - import { $isQueryBlockNode } from './plugins/query-block/node'
 - import { DELETE_QUERY_BLOCK_COMMAND } from './plugins/query-block'
 - import type { CustomTextNode } from './plugins/custom-text/node'
 - import { registerLexicalTextEntity } from './utils'
 - 
 - export type UseSelectOrDeleteHandler = (nodeKey: string, command?: LexicalCommand<undefined>) => [RefObject<HTMLDivElement>, boolean]
 - export const useSelectOrDelete: UseSelectOrDeleteHandler = (nodeKey: string, command?: LexicalCommand<undefined>) => {
 -   const ref = useRef<HTMLDivElement>(null)
 -   const [editor] = useLexicalComposerContext()
 -   const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey)
 - 
 -   const handleDelete = useCallback(
 -     (event: KeyboardEvent) => {
 -       const selection = $getSelection()
 -       const nodes = selection?.getNodes()
 -       if (
 -         !isSelected
 -         && nodes?.length === 1
 -         && (
 -           ($isContextBlockNode(nodes[0]) && command === DELETE_CONTEXT_BLOCK_COMMAND)
 -           || ($isHistoryBlockNode(nodes[0]) && command === DELETE_HISTORY_BLOCK_COMMAND)
 -           || ($isQueryBlockNode(nodes[0]) && command === DELETE_QUERY_BLOCK_COMMAND)
 -         )
 -       )
 -         editor.dispatchCommand(command, undefined)
 - 
 -       if (isSelected && $isNodeSelection(selection)) {
 -         event.preventDefault()
 -         const node = $getNodeByKey(nodeKey)
 -         if ($isDecoratorNode(node)) {
 -           if (command)
 -             editor.dispatchCommand(command, undefined)
 - 
 -           node.remove()
 -           return true
 -         }
 -       }
 - 
 -       return false
 -     },
 -     [isSelected, nodeKey, command, editor],
 -   )
 - 
 -   const handleSelect = useCallback((e: MouseEvent) => {
 -     if (!e.metaKey && !e.ctrlKey) {
 -       e.stopPropagation()
 -       clearSelection()
 -       setSelected(true)
 -     }
 -   }, [setSelected, clearSelection])
 - 
 -   useEffect(() => {
 -     const ele = ref.current
 - 
 -     if (ele)
 -       ele.addEventListener('click', handleSelect)
 - 
 -     return () => {
 -       if (ele)
 -         ele.removeEventListener('click', handleSelect)
 -     }
 -   }, [handleSelect])
 -   useEffect(() => {
 -     return mergeRegister(
 -       editor.registerCommand(
 -         KEY_DELETE_COMMAND,
 -         handleDelete,
 -         COMMAND_PRIORITY_LOW,
 -       ),
 -       editor.registerCommand(
 -         KEY_BACKSPACE_COMMAND,
 -         handleDelete,
 -         COMMAND_PRIORITY_LOW,
 -       ),
 -     )
 -   }, [editor, clearSelection, handleDelete])
 - 
 -   return [ref, isSelected]
 - }
 - 
 - export type UseTriggerHandler = () => [RefObject<HTMLDivElement>, boolean, Dispatch<SetStateAction<boolean>>]
 - export const useTrigger: UseTriggerHandler = () => {
 -   const triggerRef = useRef<HTMLDivElement>(null)
 -   const [open, setOpen] = useState(false)
 -   const handleOpen = useCallback((e: MouseEvent) => {
 -     e.stopPropagation()
 -     setOpen(v => !v)
 -   }, [])
 - 
 -   useEffect(() => {
 -     const trigger = triggerRef.current
 -     if (trigger)
 -       trigger.addEventListener('click', handleOpen)
 - 
 -     return () => {
 -       if (trigger)
 -         trigger.removeEventListener('click', handleOpen)
 -     }
 -   }, [handleOpen])
 - 
 -   return [triggerRef, open, setOpen]
 - }
 - 
 - export function useLexicalTextEntity<T extends TextNode>(
 -   getMatch: (text: string) => null | EntityMatch,
 -   targetNode: Klass<T>,
 -   createNode: (textNode: CustomTextNode) => T,
 - ) {
 -   const [editor] = useLexicalComposerContext()
 - 
 -   useEffect(() => {
 -     return mergeRegister(...registerLexicalTextEntity(editor, getMatch, targetNode, createNode))
 -   }, [createNode, editor, getMatch, targetNode])
 - }
 - 
 - export type MenuTextMatch = {
 -   leadOffset: number
 -   matchingString: string
 -   replaceableString: string
 - }
 - export type TriggerFn = (
 -   text: string,
 -   editor: LexicalEditor,
 - ) => MenuTextMatch | null
 - export const PUNCTUATION = '\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%\'"~=<>_:;'
 - export function useBasicTypeaheadTriggerMatch(
 -   trigger: string,
 -   { minLength = 1, maxLength = 75 }: { minLength?: number; maxLength?: number },
 - ): TriggerFn {
 -   return useCallback(
 -     (text: string) => {
 -       const validChars = `[${PUNCTUATION}\\s]`
 -       const TypeaheadTriggerRegex = new RegExp(
 -         '(.*)('
 -           + `[${trigger}]`
 -           + `((?:${validChars}){0,${maxLength}})`
 -           + ')$',
 -       )
 -       const match = TypeaheadTriggerRegex.exec(text)
 -       if (match !== null) {
 -         const maybeLeadingWhitespace = match[1]
 -         const matchingString = match[3]
 -         if (matchingString.length >= minLength) {
 -           return {
 -             leadOffset: match.index + maybeLeadingWhitespace.length,
 -             matchingString,
 -             replaceableString: match[2],
 -           }
 -         }
 -       }
 -       return null
 -     },
 -     [maxLength, minLength, trigger],
 -   )
 - }
 
 
  |