diff --git a/packages/slate-utils/src/transforms/toggleMark.ts b/packages/slate-utils/src/transforms/toggleMark.ts index 36f0843419..b36c20e2e7 100644 --- a/packages/slate-utils/src/transforms/toggleMark.ts +++ b/packages/slate-utils/src/transforms/toggleMark.ts @@ -25,7 +25,7 @@ export const toggleMark = ( const isActive = isMarkActive(editor, key); if (isActive) { - removeMark(editor, { key }); + editor.removeMark(key); return; } diff --git a/packages/table/src/withMarkTable.tsx b/packages/table/src/withMarkTable.tsx new file mode 100644 index 0000000000..0ae240f95f --- /dev/null +++ b/packages/table/src/withMarkTable.tsx @@ -0,0 +1,97 @@ +import { + getNodeEntries, + isCollapsed, + isText, + PlateEditor, + setNodes, + unsetNodes, + Value, +} from '@udecode/plate-common'; + +import { getTableGridAbove } from './queries'; + +export const withMarkTable = < + V extends Value = Value, + E extends PlateEditor = PlateEditor, +>( + editor: E +) => { + const { addMark, removeMark, getMarks } = editor; + + editor.addMark = (key: string, value: any) => { + const { selection } = editor; + if (!selection || isCollapsed(selection)) return addMark(key, value); + + const matchesCell = getTableGridAbove(editor, { format: 'cell' }); + + if (matchesCell.length === 0) return addMark(key, value); + + matchesCell.forEach(([cell, cellPath]) => { + setNodes( + editor, + //@ts-ignore + { + [key]: value, + }, + { + at: cellPath, + match: (n) => isText(n), + split: true, + voids: true, + } + ); + }); + }; + + editor.removeMark = (key: string) => { + const { selection } = editor; + if (!selection || isCollapsed(selection)) return removeMark(key); + + const matchesCell = getTableGridAbove(editor, { format: 'cell' }); + + if (matchesCell.length === 0) return removeMark(key); + + matchesCell.forEach(([cell, cellPath]) => { + unsetNodes(editor, key, { + at: cellPath, + match: (n) => isText(n), + split: true, + voids: true, + }); + }); + }; + + editor.getMarks = () => { + const { selection } = editor; + + if (!selection || isCollapsed(selection)) return getMarks(); + + const matchesCell = getTableGridAbove(editor, { format: 'cell' }); + + if (matchesCell.length === 0) return getMarks(); + + const totalMarks: Record = {}; + + matchesCell.forEach(([cell, cellPath]) => { + const textNodeEntry = getNodeEntries(editor, { + at: cellPath, + match: (n) => isText(n), + }); + + Array.from(textNodeEntry, (item) => item[0]).forEach((item) => { + const keys = Object.keys(item); + if (keys.length === 1) return; + + keys.splice(keys.indexOf('text'), 1); + + keys.forEach((k) => { + totalMarks[k] = true; + }); + }); + }); + + return totalMarks; + }; + + return editor; +}; diff --git a/packages/table/src/withTable.ts b/packages/table/src/withTable.ts index 71392dde4e..b2af05cb78 100644 --- a/packages/table/src/withTable.ts +++ b/packages/table/src/withTable.ts @@ -5,6 +5,7 @@ import { withDeleteTable } from './withDeleteTable'; import { withGetFragmentTable } from './withGetFragmentTable'; import { withInsertFragmentTable } from './withInsertFragmentTable'; import { withInsertTextTable } from './withInsertTextTable'; +import { withMarkTable } from './withMarkTable'; import { withNormalizeTable } from './withNormalizeTable'; import { withSelectionTable } from './withSelectionTable'; import { withSetFragmentDataTable } from './withSetFragmentDataTable'; @@ -23,6 +24,7 @@ export const withTable = < editor = withInsertTextTable(editor, plugin); editor = withSelectionTable(editor); editor = withSetFragmentDataTable(editor); + editor = withMarkTable(editor); return editor; };