簡體   English   中英

無法選擇文本,無法在 Firefox 中定位插入符號 - Slatejs

[英]Cant select text, cant position caret in Firefox - Slatejs

描述

僅在 Firefox 中的 Slatejs 編輯器因文本選擇和插入符號定位(通過鼠標)而失敗。 它總是在第一個字符之前選擇位置(路徑 [0] 偏移 [0])。 您仍然可以使用鍵盤來選擇文本和位置插入符號。

記錄

火狐: 在此處輸入圖片說明

鉻合金: https://i.imgur.com/UdH1xM7.gif

期待

它應該像在其他瀏覽器中一樣選擇文本並定位插入符號。

環境

  • 石板版本:0.63.0
  • 操作系統:Windows 10
  • 瀏覽器:Firefox 90.0.1(64 位)

編輯器實現供參考

import React, { useCallback, useMemo, useState } from "react";
import { 
    BaseEditor, 
    createEditor, 
    Descendant, 
    Editor, 
    Element as SlateElement, 
    Node, 
    Text, 
    Transforms 
} from "slate";
import { Slate, Editable, ReactEditor, withReact } from "slate-react";
import { HistoryEditor, withHistory } from "slate-history";

export type CustomEditor = BaseEditor & ReactEditor & HistoryEditor

export type ParagraphElement = {
    type: 'paragraph'
    children: CustomText[]
}
  
export type TitleElement = {
    type: "title"
    children: CustomText[]
}

type CustomElement = ParagraphElement | TitleElement;
type FormattedText = { text: string, bold?: true };
type CustomText = FormattedText;


declare module "slate" {
    interface CustomTypes {
        Editor: CustomEditor
        Element: CustomElement
        Text: FormattedText
    }
}

////////////////////////////////////
// Custom helpers
////////////////////////////////////
const customEditor = {
    isBoldMarkActive(editor: CustomEditor) {
        const [match] = Editor.nodes(editor, {
          match: (n: any) => n.bold === true,
          universal: true,
        })
        return !!match
      },
      isTitleActive(editor: CustomEditor) {
        const [match] = Editor.nodes(editor, {
          match: (n: any) => n.type === "title",
        })
        return !!match
      },
      toggleBoldMark(editor: CustomEditor) {
        const isActive = customEditor.isBoldMarkActive(editor)
        Transforms.setNodes(
          editor,
          { bold: isActive ? undefined : true },
          { match: n => Text.isText(n), split: true }
        )
      },
      toggleTitle(editor: CustomEditor) {
        const isActive = customEditor.isTitleActive(editor)
        Transforms.setNodes(
          editor,
          { type: isActive ? undefined : "title" },
          { match: n => Editor.isBlock(editor, n) }
        )
      },
}
////////////////////////////////////
// Forced layout setup - title + paragraph
////////////////////////////////////
const withLayout = (editor: CustomEditor) => {
    const { normalizeNode } = editor
  
    editor.normalizeNode = ([node, path]) => {
      if (path.length === 0) {
        if (editor.children.length < 1) {
          const title: TitleElement = {
            type: "title",
            children: [{ text: 'Untitled' }],
          }
          Transforms.insertNodes(editor, title, { at: path.concat(0) })
        }
  
        if (editor.children.length < 2) {
          const paragraph: ParagraphElement = {
            type: 'paragraph',
            children: [{ text: '' }],
          }
          Transforms.insertNodes(editor, paragraph, { at: path.concat(1) })
        }
  
        for (const [child, childPath] of Node.children(editor, path)) {
          const type = childPath[0] === 0 ? "title" : 'paragraph'
  
          if (SlateElement.isElement(child) && child.type !== type) {
            const newProperties: Partial<SlateElement> = { type }
            Transforms.setNodes(editor, newProperties, { at: childPath })
          }
        }
      }
      return normalizeNode([node, path]);
    }
    return editor;
  }
////////////////////////////////////

const TextEditor = () => {
    const initialValue: Descendant[] = [
        { 
            type: 'title',
            children: [{ text: 'Enter a title...' }],
        },
        {
            type: 'paragraph',
            children: [{ text: 'Enter your question'}]
        }
    ];

    const editor = useMemo(() => withLayout(withHistory(withReact(createEditor()))), []);
    Transforms.deselect(editor);
    const [value, setValue] = useState<Descendant[]>(initialValue);

    const renderElement = useCallback((props) => <Element {...props} />, [])
    // Define a leaf rendering function that is memoized with `useCallback`.
    const renderLeaf = useCallback((props) => {
        return <Leaf {...props} />
    }, []);
    
    return (
        // Add the editable component inside the context.
        <Slate
            editor={editor}
            value={value}
            onChange={(value) => setValue(value)}
        >
            <div>
                <button
                  onMouseDown={event => {
                    event.preventDefault()
                    customEditor.toggleBoldMark(editor)
                  }}
                >
                  B
                </button>
                <button
                  onMouseDown={event => {
                    event.preventDefault()
                    customEditor.toggleTitle(editor)
                  }}
                >
                  H2
                </button>
            </div>
            <Editable
                renderElement={renderElement}
                autoFocus
                renderLeaf={renderLeaf}
            />
        </Slate>
    )
}

export default TextEditor

// Define a React component to render leaves with bold text.
const Leaf = (props: any) => {
  return (
    <span
      {...props.attributes}
      style={{ fontWeight: props.leaf.bold ? 'bold' : 'normal' }}
    >
      {props.children}
    </span>
  )
}

const Element = ({ attributes, children, element }: any) => {
    switch (element.type) {
        case 'title':
            return <h2 {...attributes}>{children}</h2>
        case 'paragraph':
            return <p {...attributes}>{children}</p>
        default:
            return <p {...attributes}>{children}</p>
    }
}

任何想法可能導致它?

愚蠢的錯誤。 我的 CSS 重置文件包含:“用戶選擇:無”,Chrome 以某種方式忽略了該文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM