Skip to content

Commit

Permalink
Merge branch 'main' into flowflow
Browse files Browse the repository at this point in the history
  • Loading branch information
potatowagon authored Oct 25, 2024
2 parents 57bac4b + 409c65e commit 25b9a6a
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 35 deletions.
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
"@types/prismjs": "^1.26.0",
"@types/react": "^18.0.8",
"@types/react-dom": "^18.0.3",
"@types/trusted-types": "^2.0.7",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"child-process-promise": "^2.2.1",
Expand Down
15 changes: 14 additions & 1 deletion packages/lexical-clipboard/src/clipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ export function $insertDataTransferForRichText(
if (htmlString) {
try {
const parser = new DOMParser();
const dom = parser.parseFromString(htmlString, 'text/html');
const dom = parser.parseFromString(
trustHTML(htmlString) as string,
'text/html',
);
const nodes = $generateNodesFromDOM(editor, dom);
return $insertGeneratedNodes(editor, nodes, selection);
} catch {
Expand Down Expand Up @@ -192,6 +195,16 @@ export function $insertDataTransferForRichText(
}
}

function trustHTML(html: string): string | TrustedHTML {
if (window.trustedTypes && window.trustedTypes.createPolicy) {
const policy = window.trustedTypes.createPolicy('lexical', {
createHTML: (input) => input,
});
return policy.createHTML(html);
}
return html;
}

/**
* Inserts Lexical nodes into the editor using different strategies depending on
* some simple selection-based heuristics. If you're looking for a generic way to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {NodeKey} from 'lexical';

import {AppState, BinaryFiles} from '@excalidraw/excalidraw/types/types';
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {useLexicalEditable} from '@lexical/react/useLexicalEditable';
import {useLexicalNodeSelection} from '@lexical/react/useLexicalNodeSelection';
import {mergeRegister} from '@lexical/utils';
import {
Expand Down Expand Up @@ -40,6 +41,7 @@ export default function ExcalidrawComponent({
height: 'inherit' | number;
}): JSX.Element {
const [editor] = useLexicalComposerContext();
const isEditable = useLexicalEditable();
const [isModalOpen, setModalOpen] = useState<boolean>(
data === '[]' && editor.isEditable(),
);
Expand All @@ -66,16 +68,13 @@ export default function ExcalidrawComponent({
[editor, isSelected, nodeKey],
);

// Set editor to readOnly if Excalidraw is open to prevent unwanted changes
useEffect(() => {
if (isModalOpen) {
editor.setEditable(false);
} else {
editor.setEditable(true);
if (!isEditable) {
if (isSelected) {
clearSelection();
}
return;
}
}, [isModalOpen, editor]);

useEffect(() => {
return mergeRegister(
editor.registerCommand(
CLICK_COMMAND,
Expand Down Expand Up @@ -113,7 +112,15 @@ export default function ExcalidrawComponent({
COMMAND_PRIORITY_LOW,
),
);
}, [clearSelection, editor, isSelected, isResizing, $onDelete, setSelected]);
}, [
clearSelection,
editor,
isSelected,
isResizing,
$onDelete,
setSelected,
isEditable,
]);

const deleteNode = useCallback(() => {
setModalOpen(false);
Expand All @@ -130,9 +137,6 @@ export default function ExcalidrawComponent({
aps: Partial<AppState>,
fls: BinaryFiles,
) => {
if (!editor.isEditable()) {
return;
}
return editor.update(() => {
const node = $getNodeByKey(nodeKey);
if ($isExcalidrawNode(node)) {
Expand Down Expand Up @@ -198,20 +202,21 @@ export default function ExcalidrawComponent({

return (
<>
<ExcalidrawModal
initialElements={elements}
initialFiles={files}
initialAppState={appState}
isShown={isModalOpen}
onDelete={deleteNode}
onClose={closeModal}
onSave={(els, aps, fls) => {
editor.setEditable(true);
setData(els, aps, fls);
setModalOpen(false);
}}
closeOnClickOutside={false}
/>
{isEditable && isModalOpen && (
<ExcalidrawModal
initialElements={elements}
initialFiles={files}
initialAppState={appState}
isShown={isModalOpen}
onDelete={deleteNode}
onClose={closeModal}
onSave={(els, aps, fls) => {
setData(els, aps, fls);
setModalOpen(false);
}}
closeOnClickOutside={false}
/>
)}
{elements.length > 0 && (
<button
ref={buttonRef}
Expand All @@ -225,7 +230,7 @@ export default function ExcalidrawComponent({
width={width}
height={height}
/>
{isSelected && (
{isSelected && isEditable && (
<div
className="image-edit-button"
role="button"
Expand All @@ -234,7 +239,7 @@ export default function ExcalidrawComponent({
onClick={openModal}
/>
)}
{(isSelected || isResizing) && (
{(isSelected || isResizing) && isEditable && (
<ImageResizer
buttonRef={captionButtonRef}
showCaption={true}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {useLexicalEditable} from '@lexical/react/useLexicalEditable';
import {
$getTableColumnIndexFromTableCellNode,
$getTableRowIndexFromTableCellNode,
Expand All @@ -32,8 +33,9 @@ function TableHoverActionsContainer({
anchorElem,
}: {
anchorElem: HTMLElement;
}): JSX.Element {
}): JSX.Element | null {
const [editor] = useLexicalComposerContext();
const isEditable = useLexicalEditable();
const [isShownRow, setShownRow] = useState<boolean>(false);
const [isShownColumn, setShownColumn] = useState<boolean>(false);
const [shouldListenMouseMove, setShouldListenMouseMove] =
Expand Down Expand Up @@ -215,6 +217,10 @@ function TableHoverActionsContainer({
});
};

if (!isEditable) {
return null;
}

return (
<>
{isShownRow && (
Expand Down Expand Up @@ -268,8 +274,12 @@ export default function TableHoverActionsPlugin({
}: {
anchorElem?: HTMLElement;
}): React.ReactPortal | null {
return createPortal(
<TableHoverActionsContainer anchorElem={anchorElem} />,
anchorElem,
);
const isEditable = useLexicalEditable();

return isEditable
? createPortal(
<TableHoverActionsContainer anchorElem={anchorElem} />,
anchorElem,
)
: null;
}
3 changes: 3 additions & 0 deletions packages/lexical-selection/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ export function createRectsFromDOMRange(
*/
export function getStyleObjectFromRawCSS(css: string): Record<string, string> {
const styleObject: Record<string, string> = {};
if (!css) {
return styleObject;
}
const styles = css.split(';');

for (const style of styles) {
Expand Down
2 changes: 1 addition & 1 deletion packages/lexical-table/src/LexicalTableCellNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ export function $convertTableCellNodeElement(
}

const style = domNode_.style;
const textDecoration = style.textDecoration.split(' ');
const textDecoration = ((style && style.textDecoration) || '').split(' ');
const hasBoldFontWeight =
style.fontWeight === '700' || style.fontWeight === 'bold';
const hasLinethroughTextDecoration = textDecoration.includes('line-through');
Expand Down

0 comments on commit 25b9a6a

Please sign in to comment.