diff --git a/v3/cypress/e2e/text.spec.ts b/v3/cypress/e2e/text.spec.ts index 9c0c9d79a..9b5d97cfb 100644 --- a/v3/cypress/e2e/text.spec.ts +++ b/v3/cypress/e2e/text.spec.ts @@ -42,10 +42,10 @@ context("Text tile", () => { // focus the text tile t.getTextTileContent().click() const textToType = "This is some text." - t.getTextTileContent().type(textToType) + t.typeText(textToType) t.getTextTileContent().should("have.text", textToType) // blur the text tile - cy.get(".codap-container").click() + t.blurEditor() t.getTextTileContent().should("have.text", textToType) // Undo typing toolbar.getUndoTool().click() diff --git a/v3/cypress/support/elements/text-tile.ts b/v3/cypress/support/elements/text-tile.ts index ac5eaba7f..50c5fe1a4 100644 --- a/v3/cypress/support/elements/text-tile.ts +++ b/v3/cypress/support/elements/text-tile.ts @@ -9,5 +9,17 @@ export const TextTileElements = { }, getTextTileContent() { return cy.get(kTextContentClass) + }, + getTextTileEditor() { + return cy.get(".slate-editor") + }, + focusEditor() { + return this.getTextTileEditor().focus() + }, + blurEditor() { + return this.getTextTileEditor().blur() + }, + typeText(text: string) { + this.getTextTileEditor().type(text) } } diff --git a/v3/src/components/text/text-tile.tsx b/v3/src/components/text/text-tile.tsx index 6d115130c..30cf9f42b 100644 --- a/v3/src/components/text/text-tile.tsx +++ b/v3/src/components/text/text-tile.tsx @@ -5,6 +5,7 @@ import React, { useEffect, useRef, useState } from "react" import { useMemo } from "use-memo-one" import { useTileModelContext } from "../../hooks/use-tile-model-context" import { ITileBaseProps } from "../tiles/tile-base-props" +import { mstReaction } from "../../utilities/mst-reaction" import { isTextModel, modelValueToEditorValue } from "./text-model" import { TextToolbar } from "./text-toolbar" @@ -13,7 +14,7 @@ import "./text-tile.scss" export const TextTile = observer(function TextTile({ tile }: ITileBaseProps) { const textModel = isTextModel(tile?.content) ? tile.content : undefined - const { selectTile } = useTileModelContext() + const { isTileSelected } = useTileModelContext() const textOnFocus = useRef("") const [initialValue, setInitialValue] = useState(() => modelValueToEditorValue(textModel?.value)) @@ -26,6 +27,17 @@ export const TextTile = observer(function TextTile({ tile }: ITileBaseProps) { // changes to this value trigger a remount of the slate editor const mountKey = useRef(0) + useEffect(() => { + return tile && mstReaction( + () => isTileSelected() && tile?.transitionComplete, + isSelected => { + // RAF to delay focus request until after model processing completes + isSelected && requestAnimationFrame(() => ReactEditor.focus(editor)) + }, + { name: "FocusEditorOnTileSelect" }, tile + ) + }, [editor, isTileSelected, tile]) + const textTileRef = useRef(null) useEffect(() => { if (textModel) { @@ -67,19 +79,8 @@ export const TextTile = observer(function TextTile({ tile }: ITileBaseProps) { } } - function handlePointerDownInTile(e: React.MouseEvent) { - const isWrapperClick = e.target === textTileRef.current - selectTile() - if (e.target === textTileRef.current) { - // clicks in the background of the tile focus the editor - isWrapperClick && ReactEditor.focus(editor) - e.preventDefault() - } - } - return ( -
+