chore: upgrade lexical
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
"@babel/plugin-transform-react-jsx": "^7.19.0",
|
||||
"@babel/preset-env": "*",
|
||||
"@babel/preset-typescript": "^7.21.5",
|
||||
"@lexical/react": "0.12.6",
|
||||
"@lexical/react": "0.13.1",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
||||
"@simplewebauthn/browser": "^8.0.2",
|
||||
"@standardnotes/authenticator": "^2.4.0",
|
||||
@@ -76,7 +76,7 @@
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^29.3.1",
|
||||
"jest-environment-jsdom": "^29.3.1",
|
||||
"lexical": "0.12.6",
|
||||
"lexical": "0.13.1",
|
||||
"lint-staged": ">=13",
|
||||
"mini-css-extract-plugin": "^2.7.2",
|
||||
"minimatch": "^5.1.1",
|
||||
@@ -109,7 +109,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ariakit/react": "^0.3.9",
|
||||
"@lexical/headless": "0.12.6",
|
||||
"@lexical/headless": "0.13.1",
|
||||
"@radix-ui/react-slot": "^1.0.1",
|
||||
"@react-pdf/renderer": "^3.3.2",
|
||||
"comlink": "^4.4.1",
|
||||
|
||||
@@ -27,7 +27,7 @@ import { RemoveBrokenTablesPlugin } from './Plugins/TablePlugin'
|
||||
import TableActionMenuPlugin from './Plugins/TableCellActionMenuPlugin'
|
||||
import ToolbarPlugin from './Plugins/ToolbarPlugin/ToolbarPlugin'
|
||||
import { useMediaQuery, MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||
import { CheckListPlugin } from './Plugins/List/CheckListPlugin'
|
||||
import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'
|
||||
import RemoteImagePlugin from './Plugins/RemoteImagePlugin/RemoteImagePlugin'
|
||||
import CodeOptionsPlugin from './Plugins/CodeOptionsPlugin/CodeOptions'
|
||||
import { SuperSearchContextProvider } from './Plugins/SearchPlugin/Context'
|
||||
|
||||
@@ -17,7 +17,6 @@ import { BubbleNode } from '../../Plugins/ItemBubblePlugin/Nodes/BubbleNode'
|
||||
import { RemoteImageNode } from '../../Plugins/RemoteImagePlugin/RemoteImageNode'
|
||||
import { InlineFileNode } from '../../Plugins/InlineFilePlugin/InlineFileNode'
|
||||
import { CreateEditorArgs } from 'lexical'
|
||||
import { ListHTMLExportNode } from '../../Plugins/List/ListHTMLExportNode'
|
||||
import { FileExportNode } from './FileExportNode'
|
||||
|
||||
const CommonNodes = [
|
||||
@@ -44,18 +43,9 @@ const CommonNodes = [
|
||||
BubbleNode,
|
||||
RemoteImageNode,
|
||||
InlineFileNode,
|
||||
ListNode,
|
||||
]
|
||||
|
||||
export const BlockEditorNodes = [...CommonNodes, ListNode]
|
||||
export const BlockEditorNodes = CommonNodes
|
||||
|
||||
export const SuperExportNodes: CreateEditorArgs['nodes'] = [
|
||||
...CommonNodes,
|
||||
FileExportNode,
|
||||
ListHTMLExportNode,
|
||||
{
|
||||
replace: ListNode,
|
||||
with(node) {
|
||||
return new ListHTMLExportNode(node.getListType(), node.getStart())
|
||||
},
|
||||
},
|
||||
]
|
||||
export const SuperExportNodes: CreateEditorArgs['nodes'] = [...CommonNodes, FileExportNode]
|
||||
|
||||
@@ -60,6 +60,7 @@ const BlocksEditorTheme: EditorThemeClasses = {
|
||||
},
|
||||
olDepth: ['Lexical__ol1', 'Lexical__ol2', 'Lexical__ol3', 'Lexical__ol4', 'Lexical__ol5'],
|
||||
ul: 'Lexical__ul',
|
||||
checklist: 'Lexical__checkList',
|
||||
},
|
||||
ltr: 'Lexical__ltr',
|
||||
mark: 'Lexical__mark',
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
min-height: 18px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.Lexical__listItemUnchecked:before,
|
||||
.Lexical__listItemChecked:before {
|
||||
top: 0px;
|
||||
}
|
||||
.Lexical__listItemChecked:after {
|
||||
top: 1px;
|
||||
}
|
||||
.Lexical__table {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
@@ -35,13 +35,6 @@
|
||||
margin-left: 16px;
|
||||
list-style-position: outside;
|
||||
|
||||
// Fix indentation for checklists
|
||||
// Lexical doesn't support setting a class specifically for checklists at the moment
|
||||
// so we use the has selector to see if the items are check list items
|
||||
&:has(> [aria-checked]) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&.Lexical__rtl {
|
||||
margin-left: 0;
|
||||
margin-right: 16px;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { CheckListPlugin as LexicalCheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import { ListNode } from '@lexical/list'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export function CheckListPlugin() {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
|
||||
useEffect(() => {
|
||||
return editor.registerNodeTransform(ListNode, (node) => {
|
||||
if (node.getListType() !== 'check') {
|
||||
return
|
||||
}
|
||||
editor.getEditorState().read(() => {
|
||||
const element = editor.getElementByKey(node.getKey())
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
element.classList.add('Lexical__checkList')
|
||||
})
|
||||
})
|
||||
}, [editor])
|
||||
|
||||
return <LexicalCheckListPlugin />
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import { ListNode, SerializedListNode } from '@lexical/list'
|
||||
import { DOMExportOutput, LexicalEditor, Spread } from 'lexical'
|
||||
|
||||
export type SerializedListHTMLExportNode = Spread<
|
||||
{
|
||||
type: 'list-html-export'
|
||||
},
|
||||
SerializedListNode
|
||||
>
|
||||
|
||||
export class ListHTMLExportNode extends ListNode {
|
||||
static getType(): string {
|
||||
return 'list-html-export'
|
||||
}
|
||||
|
||||
static clone(node: ListNode): ListHTMLExportNode {
|
||||
return new ListHTMLExportNode(node.getListType(), node.getStart(), node.getKey())
|
||||
}
|
||||
|
||||
static importJSON(serializedNode: SerializedListNode): ListNode {
|
||||
return super.importJSON(serializedNode)
|
||||
}
|
||||
|
||||
exportDOM(editor: LexicalEditor): DOMExportOutput {
|
||||
const { element } = super.exportDOM(editor)
|
||||
if (this.getListType() === 'check' && element instanceof HTMLElement) {
|
||||
element.classList.add('Lexical__checkList')
|
||||
}
|
||||
return { element }
|
||||
}
|
||||
|
||||
exportJSON(): SerializedListHTMLExportNode {
|
||||
return {
|
||||
...super.exportJSON(),
|
||||
type: 'list-html-export',
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
DEPRECATED_GridCellNode,
|
||||
ElementNode,
|
||||
$createParagraphNode,
|
||||
$getRoot,
|
||||
@@ -16,8 +15,6 @@ import {
|
||||
$isParagraphNode,
|
||||
$isRangeSelection,
|
||||
$isTextNode,
|
||||
DEPRECATED_$getNodeTriplet,
|
||||
DEPRECATED_$isGridCellNode,
|
||||
} from 'lexical'
|
||||
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
@@ -25,6 +22,7 @@ import useLexicalEditable from '@lexical/react/useLexicalEditable'
|
||||
import {
|
||||
$deleteTableColumn__EXPERIMENTAL,
|
||||
$deleteTableRow__EXPERIMENTAL,
|
||||
$getNodeTriplet,
|
||||
$getTableCellNodeFromLexicalNode,
|
||||
$getTableColumnIndexFromTableCellNode,
|
||||
$getTableNodeFromLexicalNodeOrThrow,
|
||||
@@ -33,13 +31,13 @@ import {
|
||||
$insertTableRow__EXPERIMENTAL,
|
||||
$isTableCellNode,
|
||||
$isTableRowNode,
|
||||
$isTableSelection,
|
||||
$unmergeCell,
|
||||
getTableSelectionFromTableElement,
|
||||
getTableObserverFromTableElement,
|
||||
HTMLTableElementWithWithTableSelectionState,
|
||||
TableCellHeaderStates,
|
||||
TableCellNode,
|
||||
GridSelection,
|
||||
$isGridSelection,
|
||||
TableSelection,
|
||||
} from '@lexical/table'
|
||||
import { ReactPortal, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
@@ -50,7 +48,7 @@ import Menu from '@/Components/Menu/Menu'
|
||||
import MenuItem from '@/Components/Menu/MenuItem'
|
||||
import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator'
|
||||
|
||||
function computeSelectionCount(selection: GridSelection): {
|
||||
function computeSelectionCount(selection: TableSelection): {
|
||||
columns: number
|
||||
rows: number
|
||||
} {
|
||||
@@ -63,7 +61,7 @@ function computeSelectionCount(selection: GridSelection): {
|
||||
|
||||
// This is important when merging cells as there is no good way to re-merge weird shapes (a result
|
||||
// of selecting merged cells and non-merged)
|
||||
function isGridSelectionRectangular(selection: GridSelection): boolean {
|
||||
function isGridSelectionRectangular(selection: TableSelection): boolean {
|
||||
const nodes = selection.getNodes()
|
||||
const currentRows: Array<number> = []
|
||||
let currentRow = null
|
||||
@@ -103,16 +101,16 @@ function $canUnmerge(): boolean {
|
||||
const selection = $getSelection()
|
||||
if (
|
||||
($isRangeSelection(selection) && !selection.isCollapsed()) ||
|
||||
($isGridSelection(selection) && !selection.anchor.is(selection.focus)) ||
|
||||
(!$isRangeSelection(selection) && !$isGridSelection(selection))
|
||||
($isTableSelection(selection) && !selection.anchor.is(selection.focus)) ||
|
||||
(!$isRangeSelection(selection) && !$isTableSelection(selection))
|
||||
) {
|
||||
return false
|
||||
}
|
||||
const [cell] = DEPRECATED_$getNodeTriplet(selection.anchor)
|
||||
const [cell] = $getNodeTriplet(selection.anchor)
|
||||
return cell.__colSpan > 1 || cell.__rowSpan > 1
|
||||
}
|
||||
|
||||
function $cellContainsEmptyParagraph(cell: DEPRECATED_GridCellNode): boolean {
|
||||
function $cellContainsEmptyParagraph(cell: TableCellNode): boolean {
|
||||
if (cell.getChildrenSize() !== 1) {
|
||||
return false
|
||||
}
|
||||
@@ -167,7 +165,7 @@ function TableActionMenu({ onClose, tableCellNode: _tableCellNode, cellMerge }:
|
||||
editor.getEditorState().read(() => {
|
||||
const selection = $getSelection()
|
||||
// Merge cells
|
||||
if ($isGridSelection(selection)) {
|
||||
if ($isTableSelection(selection)) {
|
||||
const currentSelectionCounts = computeSelectionCount(selection)
|
||||
updateSelectionCounts(computeSelectionCount(selection))
|
||||
setCanMergeCells(
|
||||
@@ -190,7 +188,7 @@ function TableActionMenu({ onClose, tableCellNode: _tableCellNode, cellMerge }:
|
||||
throw new Error('Expected to find tableElement in DOM')
|
||||
}
|
||||
|
||||
const tableSelection = getTableSelectionFromTableElement(tableElement)
|
||||
const tableSelection = getTableObserverFromTableElement(tableElement)
|
||||
if (tableSelection !== null) {
|
||||
tableSelection.clearHighlight()
|
||||
}
|
||||
@@ -207,13 +205,13 @@ function TableActionMenu({ onClose, tableCellNode: _tableCellNode, cellMerge }:
|
||||
const mergeTableCellsAtSelection = () => {
|
||||
editor.update(() => {
|
||||
const selection = $getSelection()
|
||||
if ($isGridSelection(selection)) {
|
||||
if ($isTableSelection(selection)) {
|
||||
const { columns, rows } = computeSelectionCount(selection)
|
||||
const nodes = selection.getNodes()
|
||||
let firstCell: null | DEPRECATED_GridCellNode = null
|
||||
let firstCell: null | TableCellNode = null
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i]
|
||||
if (DEPRECATED_$isGridCellNode(node)) {
|
||||
if ($isTableCellNode(node)) {
|
||||
if (firstCell === null) {
|
||||
node.setColSpan(columns).setRowSpan(rows)
|
||||
firstCell = node
|
||||
@@ -222,7 +220,7 @@ function TableActionMenu({ onClose, tableCellNode: _tableCellNode, cellMerge }:
|
||||
if (isEmpty && $isParagraphNode((firstChild = node.getFirstChild()))) {
|
||||
firstChild.remove()
|
||||
}
|
||||
} else if (DEPRECATED_$isGridCellNode(firstCell)) {
|
||||
} else if ($isTableCellNode(firstCell)) {
|
||||
const isEmpty = $cellContainsEmptyParagraph(node)
|
||||
if (!isEmpty) {
|
||||
firstCell.append(...node.getChildren())
|
||||
|
||||
@@ -44,7 +44,7 @@ ${superEditorCSS.toString()}
|
||||
${exportOverridesCSS.toString()}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body style="--font-size: 1rem; --line-height: 1.5; font-size: var(--font-size); line-height: var(--line-height);">
|
||||
${content}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user