From 04733f0db1c3c2592dfd8b4122111b8c85eede4b Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Fri, 10 Jan 2025 14:13:06 -0700 Subject: [PATCH] feat(richtext-lexical): upgrade lexical from 0.20.0 to 0.21.0. Fixes table selection & scrollable table bugs (#10501) Fixes https://github.com/payloadcms/payload/issues/8036 This PR upgrades lexical from 0.20.0 to 0.21.0. As stated in the docs, please ensure you're using our re-exported lexical packages instead of installing lexical directly. E.g., import from `@payloadcms/richtext-lexical/lexical` instead of `lexical`. Direct lexical imports are not supported and may break. This PR ports over all relevant PRs from the lexical playground that have been pushed between 0.20.0 and 0.21.0. This includes a lot of bug fixes related to tables, specifically scrollable tables and table selection. --- packages/richtext-lexical/package.json | 44 +-- .../testRecorder/client/plugin/index.tsx | 8 +- .../plugins/TableActionMenuPlugin/index.scss | 15 +- .../plugins/TableActionMenuPlugin/index.tsx | 145 +++++--- .../plugins/TableCellResizerPlugin/index.tsx | 64 ++-- .../plugins/TableHoverActionsPlugin/index.tsx | 103 +++--- .../client/plugins/TablePlugin/index.scss | 53 +-- .../client/plugins/TablePlugin/index.tsx | 6 +- .../floatingLinkEditor/LinkEditor/index.tsx | 20 +- .../toolbars/inline/client/Toolbar/index.tsx | 5 +- .../LexicalTypeaheadMenuPlugin/index.tsx | 4 +- .../src/lexical/theme/EditorTheme.tsx | 6 +- pnpm-lock.yaml | 344 +++++++++--------- 13 files changed, 441 insertions(+), 376 deletions(-) diff --git a/packages/richtext-lexical/package.json b/packages/richtext-lexical/package.json index 9e17efc1b5c..290ae2ab14a 100644 --- a/packages/richtext-lexical/package.json +++ b/packages/richtext-lexical/package.json @@ -346,15 +346,15 @@ ] }, "dependencies": { - "@lexical/headless": "0.20.0", - "@lexical/html": "0.20.0", - "@lexical/link": "0.20.0", - "@lexical/list": "0.20.0", - "@lexical/mark": "0.20.0", - "@lexical/react": "0.20.0", - "@lexical/rich-text": "0.20.0", - "@lexical/selection": "0.20.0", - "@lexical/utils": "0.20.0", + "@lexical/headless": "0.21.0", + "@lexical/html": "0.21.0", + "@lexical/link": "0.21.0", + "@lexical/list": "0.21.0", + "@lexical/mark": "0.21.0", + "@lexical/react": "0.21.0", + "@lexical/rich-text": "0.21.0", + "@lexical/selection": "0.21.0", + "@lexical/utils": "0.21.0", "@payloadcms/translations": "workspace:*", "@payloadcms/ui": "workspace:*", "@types/uuid": "10.0.0", @@ -363,7 +363,7 @@ "dequal": "2.0.3", "escape-html": "1.0.3", "jsox": "1.2.121", - "lexical": "0.20.0", + "lexical": "0.21.0", "mdast-util-from-markdown": "2.0.2", "mdast-util-mdx-jsx": "3.1.3", "micromark-extension-mdx-jsx": "3.0.1", @@ -377,7 +377,7 @@ "@babel/preset-env": "7.26.0", "@babel/preset-react": "7.25.9", "@babel/preset-typescript": "7.26.0", - "@lexical/eslint-plugin": "0.20.0", + "@lexical/eslint-plugin": "0.21.0", "@payloadcms/eslint-config": "workspace:*", "@types/escape-html": "1.0.4", "@types/json-schema": "7.0.15", @@ -395,18 +395,18 @@ "peerDependencies": { "@faceless-ui/modal": "3.0.0-beta.2", "@faceless-ui/scroll-info": "2.0.0-beta.0", - "@lexical/headless": "0.20.0", - "@lexical/html": "0.20.0", - "@lexical/link": "0.20.0", - "@lexical/list": "0.20.0", - "@lexical/mark": "0.20.0", - "@lexical/react": "0.20.0", - "@lexical/rich-text": "0.20.0", - "@lexical/selection": "0.20.0", - "@lexical/table": "0.20.0", - "@lexical/utils": "0.20.0", + "@lexical/headless": "0.21.0", + "@lexical/html": "0.21.0", + "@lexical/link": "0.21.0", + "@lexical/list": "0.21.0", + "@lexical/mark": "0.21.0", + "@lexical/react": "0.21.0", + "@lexical/rich-text": "0.21.0", + "@lexical/selection": "0.21.0", + "@lexical/table": "0.21.0", + "@lexical/utils": "0.21.0", "@payloadcms/next": "workspace:*", - "lexical": "0.20.0", + "lexical": "0.21.0", "payload": "workspace:*", "react": "^19.0.0 || ^19.0.0-rc-65a56d0e-20241020", "react-dom": "^19.0.0 || ^19.0.0-rc-65a56d0e-20241020" diff --git a/packages/richtext-lexical/src/features/debug/testRecorder/client/plugin/index.tsx b/packages/richtext-lexical/src/features/debug/testRecorder/client/plugin/index.tsx index 565abb9dc5f..4bde291b85a 100644 --- a/packages/richtext-lexical/src/features/debug/testRecorder/client/plugin/index.tsx +++ b/packages/richtext-lexical/src/features/debug/testRecorder/client/plugin/index.tsx @@ -2,7 +2,7 @@ import type { BaseSelection, LexicalEditor } from 'lexical' import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js' -import { $createParagraphNode, $createTextNode, $getRoot } from 'lexical' +import { $createParagraphNode, $createTextNode, $getRoot, getDOMSelection } from 'lexical' import * as React from 'react' import { type JSX, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react' @@ -153,7 +153,7 @@ function useTestRecorder(editor: LexicalEditor): [JSX.Element, JSX.Element | nul const generateTestContent = useCallback(() => { const rootElement = editor.getRootElement() - const browserSelection = window.getSelection() + const browserSelection = getDOMSelection(editor._window) if ( rootElement == null || @@ -290,7 +290,7 @@ ${steps.map(formatStep).join(`\n`)} const skipNextSelectionChange = skipNextSelectionChangeRef.current if (previousSelection !== currentSelection) { if (dirtyLeaves.size === 0 && dirtyElements.size === 0 && !skipNextSelectionChange) { - const browserSelection = window.getSelection() + const browserSelection = getDOMSelection(editor._window) if ( browserSelection && (browserSelection.anchorNode == null || browserSelection.focusNode == null) @@ -346,7 +346,7 @@ ${steps.map(formatStep).join(`\n`)} if (!isRecording) { return } - const browserSelection = window.getSelection() + const browserSelection = getDOMSelection(editor._window) if ( browserSelection === null || browserSelection.anchorNode == null || diff --git a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableActionMenuPlugin/index.scss b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableActionMenuPlugin/index.scss index a82b2dfca74..5ff0539b129 100644 --- a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableActionMenuPlugin/index.scss +++ b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableActionMenuPlugin/index.scss @@ -8,11 +8,22 @@ will-change: transform; } + .table-cell-action-button-container.table-cell-action-button-container--active { + pointer-events: auto; + opacity: 1; + } + .table-cell-action-button-container.table-cell-action-button-container--inactive { + pointer-events: none; + opacity: 0; + } + .table-cell-action-button { - background-color: var(--theme-elevation-200); + //background-color: var(--theme-elevation-200); border: 0; padding: 2px; - position: relative; + position: absolute; + top: 10px; + right: 10px; border-radius: $style-radius-m; color: var(--theme-elevation-800); display: inline-block; diff --git a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableActionMenuPlugin/index.tsx b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableActionMenuPlugin/index.tsx index 6d1ab2c35b1..9002dfdf54a 100644 --- a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableActionMenuPlugin/index.tsx +++ b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableActionMenuPlugin/index.tsx @@ -1,10 +1,6 @@ 'use client' -import type { - HTMLTableElementWithWithTableSelectionState, - TableRowNode, - TableSelection, -} from '@lexical/table' +import type { TableObserver, TableRowNode, TableSelection } from '@lexical/table' import type { ElementNode } from 'lexical' import type { JSX } from 'react' @@ -24,10 +20,12 @@ import { $isTableRowNode, $isTableSelection, $unmergeCell, + getTableElement, getTableObserverFromTableElement, TableCellHeaderStates, TableCellNode, } from '@lexical/table' +import { mergeRegister } from '@lexical/utils' import { useScrollInfo } from '@payloadcms/ui' import { $createParagraphNode, @@ -37,6 +35,9 @@ import { $isParagraphNode, $isRangeSelection, $isTextNode, + COMMAND_PRIORITY_CRITICAL, + getDOMSelection, + SELECTION_CHANGE_COMMAND, } from 'lexical' import * as React from 'react' import { useCallback, useEffect, useRef, useState } from 'react' @@ -44,8 +45,8 @@ import { createPortal } from 'react-dom' import type { PluginComponentWithAnchor } from '../../../../typesClient.js' -import { MeatballsIcon } from '../../../../../lexical/ui/icons/Meatballs/index.js' import './index.scss' +import { MeatballsIcon } from '../../../../../lexical/ui/icons/Meatballs/index.js' function computeSelectionCount(selection: TableSelection): { columns: number @@ -201,17 +202,15 @@ function TableActionMenu({ editor.update(() => { if (tableCellNode.isAttached()) { const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode) - const tableElement = editor.getElementByKey( - tableNode.getKey(), - ) as HTMLTableElementWithWithTableSelectionState + const tableElement = getTableElement(tableNode, editor.getElementByKey(tableNode.getKey())) - if (!tableElement) { + if (tableElement === null) { throw new Error('Expected to find tableElement in DOM') } const tableObserver = getTableObserverFromTableElement(tableElement) if (tableObserver !== null) { - tableObserver.clearHighlight() + tableObserver.$clearHighlight() } tableNode.markDirty() @@ -409,7 +408,7 @@ function TableActionMenu({ onClick={() => mergeTableCellsAtSelection()} type="button" > - Merge cells + Merge cells ) } else if (canUnmergeCell) { @@ -420,7 +419,7 @@ function TableActionMenu({ onClick={() => unmergeTableCellsAtSelection()} type="button" > - Unmerge cells + Unmerge cells ) } @@ -555,8 +554,8 @@ function TableCellActionMenuContainer({ }): JSX.Element { const [editor] = useLexicalComposerContext() - const menuButtonRef = useRef(null) - const menuRootRef = useRef(null) + const menuButtonRef = useRef(null) + const menuRootRef = useRef(null) const [isMenuOpen, setIsMenuOpen] = useState(false) const [tableCellNode, setTableMenuCellNode] = useState(null) @@ -564,15 +563,23 @@ function TableCellActionMenuContainer({ const $moveMenu = useCallback(() => { const menu = menuButtonRef.current const selection = $getSelection() - const nativeSelection = window.getSelection() + const nativeSelection = getDOMSelection(editor._window) const activeElement = document.activeElement + function disable() { + if (menu) { + menu.classList.remove('table-cell-action-button-container--active') + menu.classList.add('table-cell-action-button-container--inactive') + } + setTableMenuCellNode(null) + } if (selection == null || menu == null) { - setTableMenuCellNode(null) - return + return disable() } const rootElement = editor.getRootElement() + let tableObserver: null | TableObserver = null + let tableCellParentNodeDOM: HTMLElement | null = null if ( $isRangeSelection(selection) && @@ -585,53 +592,85 @@ function TableCellActionMenuContainer({ ) if (tableCellNodeFromSelection == null) { - setTableMenuCellNode(null) - return + return disable() } - const tableCellParentNodeDOM = editor.getElementByKey(tableCellNodeFromSelection.getKey()) + tableCellParentNodeDOM = editor.getElementByKey(tableCellNodeFromSelection.getKey()) - if (tableCellParentNodeDOM == null) { - setTableMenuCellNode(null) - return + if (tableCellParentNodeDOM == null || !tableCellNodeFromSelection.isAttached()) { + return disable() } - setTableMenuCellNode(tableCellNodeFromSelection) - } else if (!activeElement) { - setTableMenuCellNode(null) - } - }, [editor]) - - useEffect(() => { - return editor.registerUpdateListener(() => { - editor.getEditorState().read(() => { - $moveMenu() - }) - }) - }) + const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNodeFromSelection) + const tableElement = getTableElement(tableNode, editor.getElementByKey(tableNode.getKey())) - useEffect(() => { - const menuButtonDOM = menuButtonRef.current as HTMLButtonElement | null + if (tableElement === null) { + throw new Error('TableActionMenu: Expected to find tableElement in DOM') + } - if (menuButtonDOM != null && tableCellNode != null) { - const tableCellNodeDOM = editor.getElementByKey(tableCellNode.getKey()) + tableObserver = getTableObserverFromTableElement(tableElement) + setTableMenuCellNode(tableCellNodeFromSelection) + } else if ($isTableSelection(selection)) { + const anchorNode = $getTableCellNodeFromLexicalNode(selection.anchor.getNode()) + if (!$isTableCellNode(anchorNode)) { + throw new Error('TableSelection anchorNode must be a TableCellNode') + } + const tableNode = $getTableNodeFromLexicalNodeOrThrow(anchorNode) + const tableElement = getTableElement(tableNode, editor.getElementByKey(tableNode.getKey())) - if (tableCellNodeDOM != null) { - const tableCellRect = tableCellNodeDOM.getBoundingClientRect() - const menuRect = menuButtonDOM.getBoundingClientRect() - const anchorRect = anchorElem.getBoundingClientRect() + if (tableElement === null) { + throw new Error('TableActionMenu: Expected to find tableElement in DOM') + } - const top = tableCellRect.top - anchorRect.top + 4 - const left = tableCellRect.right - menuRect.width - 10 - anchorRect.left + tableObserver = getTableObserverFromTableElement(tableElement) + tableCellParentNodeDOM = editor.getElementByKey(anchorNode.getKey()) + } else if (!activeElement) { + return disable() + } + if (tableObserver === null || tableCellParentNodeDOM === null) { + return disable() + } + const enabled = !tableObserver || !tableObserver.isSelecting + menu.classList.toggle('table-cell-action-button-container--active', enabled) + menu.classList.toggle('table-cell-action-button-container--inactive', !enabled) + if (enabled) { + const tableCellRect = tableCellParentNodeDOM.getBoundingClientRect() + const anchorRect = anchorElem.getBoundingClientRect() + const top = tableCellRect.top - anchorRect.top + const left = tableCellRect.right - anchorRect.left + menu.style.transform = `translate(${left}px, ${top}px)` + } + }, [editor, anchorElem]) - menuButtonDOM.style.opacity = '1' - menuButtonDOM.style.transform = `translate(${left}px, ${top}px)` - } else { - menuButtonDOM.style.opacity = '0' - menuButtonDOM.style.transform = 'translate(-10000px, -10000px)' + useEffect(() => { + // We call the $moveMenu callback every time the selection changes, + // once up front, and once after each mouseUp + let timeoutId: ReturnType | undefined = undefined + const callback = () => { + timeoutId = undefined + editor.getEditorState().read($moveMenu) + } + const delayedCallback = () => { + if (timeoutId === undefined) { + timeoutId = setTimeout(callback, 0) } + return false } - }, [menuButtonRef, tableCellNode, editor, anchorElem]) + return mergeRegister( + editor.registerUpdateListener(delayedCallback), + editor.registerCommand(SELECTION_CHANGE_COMMAND, delayedCallback, COMMAND_PRIORITY_CRITICAL), + editor.registerRootListener((rootElement, prevRootElement) => { + if (prevRootElement) { + prevRootElement.removeEventListener('mouseup', delayedCallback) + } + if (rootElement) { + rootElement.addEventListener('mouseup', delayedCallback) + delayedCallback() + } + }), + () => clearTimeout(timeoutId), + ) + }) const prevTableCellDOM = useRef(tableCellNode) diff --git a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableCellResizerPlugin/index.tsx b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableCellResizerPlugin/index.tsx index 4a35614e71b..6a0a90a95dd 100644 --- a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableCellResizerPlugin/index.tsx +++ b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableCellResizerPlugin/index.tsx @@ -13,6 +13,7 @@ import { $isTableCellNode, $isTableRowNode, getDOMCellFromTarget, + getTableElement, TableNode, } from '@lexical/table' import { calculateZoomLevel } from '@lexical/utils' @@ -76,27 +77,27 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element { useEffect(() => { const onMouseMove = (event: MouseEvent) => { - setTimeout(() => { - const target = event.target - - if (draggingDirection) { - updateMouseCurrentPos({ - x: event.clientX, - y: event.clientY, - }) - return - } - updateIsMouseDown(isMouseDownOnEvent(event)) - if (resizerRef.current && resizerRef.current.contains(target as Node)) { - return - } + const target = event.target - if (targetRef.current !== target) { - targetRef.current = target as HTMLElement - const cell = getDOMCellFromTarget(target as HTMLElement) + if (draggingDirection) { + updateMouseCurrentPos({ + x: event.clientX, + y: event.clientY, + }) + return + } + updateIsMouseDown(isMouseDownOnEvent(event)) + if (resizerRef.current && resizerRef.current.contains(target as Node)) { + return + } - if (cell && activeCell !== cell) { - editor.update(() => { + if (targetRef.current !== target) { + targetRef.current = target as HTMLElement + const cell = getDOMCellFromTarget(target as HTMLElement) + + if (cell && activeCell !== cell) { + editor.getEditorState().read( + () => { const tableCellNode = $getNearestNodeFromDOMNode(cell.elem) if (!tableCellNode) { @@ -104,8 +105,10 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element { } const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode) - const tableElement = editor.getElementByKey(tableNode.getKey()) - + const tableElement = getTableElement( + tableNode, + editor.getElementByKey(tableNode.getKey()), + ) if (!tableElement) { throw new Error('TableCellResizer: Table element not found.') } @@ -113,24 +116,21 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element { targetRef.current = target as HTMLElement tableRectRef.current = tableElement.getBoundingClientRect() updateActiveCell(cell) - }) - } else if (cell == null) { - resetState() - } + }, + { editor }, + ) + } else if (cell == null) { + resetState() } - }, 0) + } } const onMouseDown = (event: MouseEvent) => { - setTimeout(() => { - updateIsMouseDown(true) - }, 0) + updateIsMouseDown(true) } const onMouseUp = (event: MouseEvent) => { - setTimeout(() => { - updateIsMouseDown(false) - }, 0) + updateIsMouseDown(false) } const removeRootListener = editor.registerRootListener((rootElement, prevRootElement) => { diff --git a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableHoverActionsPlugin/index.tsx b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableHoverActionsPlugin/index.tsx index ca912b4fccc..67e26a319d6 100644 --- a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableHoverActionsPlugin/index.tsx +++ b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableHoverActionsPlugin/index.tsx @@ -6,12 +6,14 @@ import type { JSX } from 'react' import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' import { + $getTableAndElementByKey, $getTableColumnIndexFromTableCellNode, $getTableRowIndexFromTableCellNode, $insertTableColumn__EXPERIMENTAL, $insertTableRow__EXPERIMENTAL, $isTableCellNode, $isTableNode, + getTableElement, TableNode, } from '@lexical/table' import { $findMatchingParent, mergeRegister } from '@lexical/utils' @@ -59,34 +61,35 @@ function TableHoverActionsContainer({ let hoveredColumnNode: null | TableCellNode = null let tableDOMElement: HTMLElement | null = null - editor.update(() => { - const maybeTableCell = $getNearestNodeFromDOMNode(tableDOMNode) + editor.getEditorState().read( + () => { + const maybeTableCell = $getNearestNodeFromDOMNode(tableDOMNode) - if ($isTableCellNode(maybeTableCell)) { - const table = $findMatchingParent(maybeTableCell, (node) => $isTableNode(node)) - if (!$isTableNode(table)) { - return - } + if ($isTableCellNode(maybeTableCell)) { + const table = $findMatchingParent(maybeTableCell, (node) => $isTableNode(node)) + if (!$isTableNode(table)) { + return + } - tableDOMElement = editor.getElementByKey(table?.getKey()) + tableDOMElement = getTableElement(table, editor.getElementByKey(table.getKey())) - if (tableDOMElement) { - const rowCount = table.getChildrenSize() - const colCount = - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - ((table as TableNode).getChildAtIndex(0) as TableRowNode)?.getChildrenSize() + if (tableDOMElement) { + const rowCount = table.getChildrenSize() + const colCount = (table.getChildAtIndex(0) as TableRowNode)?.getChildrenSize() - const rowIndex = $getTableRowIndexFromTableCellNode(maybeTableCell) - const colIndex = $getTableColumnIndexFromTableCellNode(maybeTableCell) + const rowIndex = $getTableRowIndexFromTableCellNode(maybeTableCell) + const colIndex = $getTableColumnIndexFromTableCellNode(maybeTableCell) - if (rowIndex === rowCount - 1) { - hoveredRowNode = maybeTableCell - } else if (colIndex === colCount - 1) { - hoveredColumnNode = maybeTableCell + if (rowIndex === rowCount - 1) { + hoveredRowNode = maybeTableCell + } else if (colIndex === colCount - 1) { + hoveredColumnNode = maybeTableCell + } } } - } - }) + }, + { editor }, + ) if (tableDOMElement) { const { @@ -154,37 +157,37 @@ function TableHoverActionsContainer({ editor.registerMutationListener( TableNode, (mutations) => { - editor.getEditorState().read(() => { - for (const [key, type] of mutations) { - const tableDOMElement = editor.getElementByKey(key) - - switch (type) { - case 'created': - tableSetRef.current.add(key) - setShouldListenMouseMove(tableSetRef.current.size > 0) - if (tableDOMElement) { - tableResizeObserver.observe(tableDOMElement) + editor.getEditorState().read( + () => { + let resetObserver = false + for (const [key, type] of mutations) { + switch (type) { + case 'created': { + tableSetRef.current.add(key) + resetObserver = true + break } - break - - case 'destroyed': - tableSetRef.current.delete(key) - setShouldListenMouseMove(tableSetRef.current.size > 0) - // Reset resize observers - tableResizeObserver.disconnect() - tableSetRef.current.forEach((tableKey: NodeKey) => { - const tableElement = editor.getElementByKey(tableKey) - if (tableElement) { - tableResizeObserver.observe(tableElement) - } - }) - break - - default: - break + case 'destroyed': { + tableSetRef.current.delete(key) + resetObserver = true + break + } + default: + break + } } - } - }) + if (resetObserver) { + // Reset resize observers + tableResizeObserver.disconnect() + for (const tableKey of tableSetRef.current) { + const { tableElement } = $getTableAndElementByKey(tableKey) + tableResizeObserver.observe(tableElement) + } + setShouldListenMouseMove(tableSetRef.current.size > 0) + } + }, + { editor }, + ) }, { skipInitialization: false }, ), diff --git a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TablePlugin/index.scss b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TablePlugin/index.scss index b6b73a28ccc..d34ba628f21 100644 --- a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TablePlugin/index.scss +++ b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TablePlugin/index.scss @@ -2,6 +2,19 @@ @layer payload-default { .LexicalEditorTheme { + &__tableScrollableWrapper { + overflow-x: auto; + margin: 0px 25px 30px 0px; + } + &__tableScrollableWrapper > .LexicalEditorTheme__table { + /* Remove the table's margin and put it on the wrapper */ + margin: 0; + } + + &__tableSelection *::selection { + background-color: transparent; + } + &__table { border-collapse: collapse; max-width: 100%; @@ -39,17 +52,6 @@ outline: none; } - &__tableCellSortedIndicator { - display: block; - opacity: 0.5; - position: absolute; - bottom: 0; - left: 0; - width: 100%; - height: 4px; - background-color: #999; - } - &__tableCellResizer { position: absolute; right: -4px; @@ -66,23 +68,19 @@ } &__tableCellSelected { - background-color: #c9dbf0; + caret-color: transparent; } - &__tableCellPrimarySelected { - border: 2px solid rgb(60, 132, 244); - display: block; - height: calc(100% - 2px); + &__tableCellSelected::after { position: absolute; - width: calc(100% - 2px); - left: -1px; - top: -1px; - z-index: 2; - } - - &__tableCellEditing { - box-shadow: 0 0 5px rgba(0, 0, 0, 0.4); - border-radius: $style-radius-m; + left: 0; + right: 0; + bottom: 0; + top: 0; + background-color: var(--color-success-250); + mix-blend-mode: multiply; + content: ''; + pointer-events: none; } &__tableAddColumns { @@ -175,6 +173,11 @@ background-color: var(--theme-elevation-50); } + &__tableCellSelected::after { + background-color: var(--color-success-700); + mix-blend-mode: screen; + } + &__tableAddColumns:after, &__tableAddRows:after { background-image: url(../../../../../lexical/ui/icons/Add/light.svg); diff --git a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TablePlugin/index.tsx b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TablePlugin/index.tsx index 3f07f6d7703..755702a6f12 100644 --- a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TablePlugin/index.tsx +++ b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TablePlugin/index.tsx @@ -143,7 +143,11 @@ export const TablePlugin: PluginComponent = () => { schemaPath={schemaPath} schemaPathSuffix="fields" /> - + ) } diff --git a/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/LinkEditor/index.tsx b/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/LinkEditor/index.tsx index c3c03220dda..7f37154d209 100644 --- a/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/LinkEditor/index.tsx +++ b/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/LinkEditor/index.tsx @@ -22,6 +22,7 @@ import { $isRangeSelection, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, + getDOMSelection, KEY_ESCAPE_COMMAND, SELECTION_CHANGE_COMMAND, } from 'lexical' @@ -40,6 +41,12 @@ import { $isAutoLinkNode } from '../../../../nodes/AutoLinkNode.js' import { $createLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from '../../../../nodes/LinkNode.js' import { TOGGLE_LINK_WITH_MODAL_COMMAND } from './commands.js' +function preventDefault( + event: React.KeyboardEvent | React.MouseEvent, +): void { + event.preventDefault() +} + export function LinkEditor({ anchorElem }: { anchorElem: HTMLElement }): React.ReactNode { const [editor] = useLexicalComposerContext() // TO-DO: There are several states that should not be state, because they @@ -203,7 +210,7 @@ export function LinkEditor({ anchorElem }: { anchorElem: HTMLElement }): React.R } const editorElem = editorRef.current - const nativeSelection = window.getSelection() + const nativeSelection = getDOMSelection(editor._window) const { activeElement } = document if (editorElem === null) { @@ -349,12 +356,11 @@ export function LinkEditor({ anchorElem }: { anchorElem: HTMLElement }): React.R