Skip to content

Commit

Permalink
Merge pull request #3923 from wststone/fix/equation-input-undo
Browse files Browse the repository at this point in the history
fix: equation input undo regession
  • Loading branch information
zbeyens committed Dec 27, 2024
1 parent 148bb2b commit b158825
Show file tree
Hide file tree
Showing 20 changed files with 829 additions and 346 deletions.
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@radix-ui/react-tooltip": "^1.1.6",
"@udecode/cmdk": "^0.1.1",
"@udecode/cn": "40.2.8",
"@udecode/plate-ai": "41.0.1",
"@udecode/plate-ai": "41.0.8",
"@udecode/plate-alignment": "41.0.0",
"@udecode/plate-autoformat": "41.0.0",
"@udecode/plate-basic-elements": "41.0.0",
Expand All @@ -41,11 +41,11 @@
"@udecode/plate-code-block": "41.0.0",
"@udecode/plate-combobox": "41.0.0",
"@udecode/plate-comments": "41.0.0",
"@udecode/plate-common": "41.0.2",
"@udecode/plate-common": "41.0.5",
"@udecode/plate-cursor": "41.0.0",
"@udecode/plate-date": "41.0.0",
"@udecode/plate-dnd": "41.0.2",
"@udecode/plate-docx": "41.0.0",
"@udecode/plate-docx": "41.0.10",
"@udecode/plate-emoji": "41.0.0",
"@udecode/plate-excalidraw": "41.0.0",
"@udecode/plate-floating": "41.0.0",
Expand All @@ -54,7 +54,7 @@
"@udecode/plate-highlight": "41.0.0",
"@udecode/plate-horizontal-rule": "41.0.0",
"@udecode/plate-indent": "41.0.0",
"@udecode/plate-indent-list": "41.0.0",
"@udecode/plate-indent-list": "41.0.10",
"@udecode/plate-juice": "41.0.0",
"@udecode/plate-kbd": "41.0.0",
"@udecode/plate-layout": "41.0.2",
Expand All @@ -68,13 +68,14 @@
"@udecode/plate-reset-node": "41.0.0",
"@udecode/plate-resizable": "41.0.0",
"@udecode/plate-select": "41.0.0",
"@udecode/plate-selection": "41.0.0",
"@udecode/plate-selection": "41.0.8",
"@udecode/plate-slash-command": "41.0.0",
"@udecode/plate-tabbable": "41.0.0",
"@udecode/plate-table": "41.0.0",
"@udecode/plate-table": "41.0.9",
"@udecode/plate-toggle": "41.0.0",
"@udecode/plate-trailing-block": "41.0.0",
"@uploadthing/react": "7.1.0",
"react-textarea-autosize": "^8.5.5",
"ai": "^4.0.21",
"class-variance-authority": "0.7.1",
"clsx": "^2.1.1",
Expand Down
395 changes: 199 additions & 196 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions src/components/editor/plugins/comments-plugin.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,52 @@
'use client';

import type { TComment } from '@udecode/plate-comments';

import { CommentsPlugin } from '@udecode/plate-comments/react';

import { CommentsPopover } from '@/components/plate-ui/comments-popover';

const commentsData: Record<string, TComment> = {
1: {
id: '1',
createdAt: 1_663_453_625_129,
userId: '1',
value: [{ children: [{ text: 'This is a comment.' }], type: 'p' }],
},
2: {
id: '2',
createdAt: 1_663_453_729_191,
userId: '1',
value: [
{ children: [{ text: 'Can you review this one @12joan?' }], type: 'p' },
],
},
3: {
id: '3',
createdAt: 1_663_453_740_180,
isResolved: true,
userId: '1',
value: [{ children: [{ text: 'This is a resolved comment.' }], type: 'p' }],
},
4: {
id: '4',
createdAt: 1_663_453_740_181,
parentId: '2',
userId: '2',
value: [{ children: [{ text: 'LGTM.' }], type: 'p' }],
},
5: {
id: '4',
createdAt: 1_663_453_740_182,
parentId: '2',
userId: '1',
value: [{ children: [{ text: 'Thanks!' }], type: 'p' }],
},
};

export const commentsPlugin = CommentsPlugin.configure({
options: {
comments: commentsData,
myUserId: '1',
users: {
1: {
Expand Down
8 changes: 2 additions & 6 deletions src/components/editor/plugins/editor-plugins.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ import { JuicePlugin } from '@udecode/plate-juice';
import { KbdPlugin } from '@udecode/plate-kbd/react';
import { ColumnPlugin } from '@udecode/plate-layout/react';
import { MarkdownPlugin } from '@udecode/plate-markdown';
import {
EquationPlugin,
InlineEquationPlugin,
} from '@udecode/plate-math/react';
import { SlashPlugin } from '@udecode/plate-slash-command/react';
import { TogglePlugin } from '@udecode/plate-toggle/react';
import { TrailingBlockPlugin } from '@udecode/plate-trailing-block';
Expand All @@ -36,6 +32,7 @@ import { commentsPlugin } from './comments-plugin';
import { cursorOverlayPlugin } from './cursor-overlay-plugin';
import { deletePlugins } from './delete-plugins';
import { dndPlugins } from './dnd-plugins';
import { equationPlugins } from './equation-plugins';
import { exitBreakPlugin } from './exit-break-plugin';
import { indentListPlugins } from './indent-list-plugins';
import { lineHeightPlugin } from './line-height-plugin';
Expand All @@ -57,8 +54,7 @@ export const viewPlugins = [
TogglePlugin,
tocPlugin,
...mediaPlugins,
InlineEquationPlugin,
EquationPlugin,
...equationPlugins,
CalloutPlugin,
ColumnPlugin,

Expand Down
6 changes: 6 additions & 0 deletions src/components/editor/plugins/equation-plugins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {
EquationPlugin,
InlineEquationPlugin,
} from '@udecode/plate-math/react';

export const equationPlugins = [InlineEquationPlugin, EquationPlugin];
12 changes: 9 additions & 3 deletions src/components/plate-ui/color-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import {
ColorDropdownMenuItems,
} from './color-dropdown-menu-items';
import { ColorCustom } from './colors-custom';
import { DropdownMenuGroup, DropdownMenuItem } from './dropdown-menu';
import {
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
} from './dropdown-menu';

export const ColorPickerContent = withRef<
'div',
Expand Down Expand Up @@ -38,7 +42,8 @@ export const ColorPickerContent = withRef<
) => {
return (
<div ref={ref} className={cn('flex flex-col', className)} {...props}>
<DropdownMenuGroup label="Custom Colors">
<DropdownMenuGroup>
<DropdownMenuLabel>Custom Colors</DropdownMenuLabel>
<ColorCustom
color={color}
className="px-2"
Expand All @@ -48,7 +53,8 @@ export const ColorPickerContent = withRef<
updateCustomColor={updateCustomColor}
/>
</DropdownMenuGroup>
<DropdownMenuGroup label="Default Colors">
<DropdownMenuGroup>
<DropdownMenuLabel>Default Colors</DropdownMenuLabel>
<ColorDropdownMenuItems
color={color}
className="px-2"
Expand Down
5 changes: 1 addition & 4 deletions src/components/plate-ui/draggable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,7 @@ export const Draggable = withRef<'div', PlateRenderElementProps>(
className={cn(
'relative',
isDragging && 'opacity-50',
STRUCTURAL_TYPES.includes(element.type)
? 'group/structural'
: 'group',
className
STRUCTURAL_TYPES.includes(element.type) ? 'group/structural' : 'group'
)}
>
<Gutter>
Expand Down
31 changes: 1 addition & 30 deletions src/components/plate-ui/dropdown-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,7 @@ export const DropdownMenu = DropdownMenuPrimitive.Root;

export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;

export const DropdownMenuGroup = React.forwardRef<
HTMLDivElement,
{ label?: React.ReactNode } & React.ComponentPropsWithoutRef<
typeof DropdownMenuPrimitive.Group
>
>(({ label, ...props }, ref) => {
return (
<>
<DropdownMenuSeparator
className={cn(
'hidden',
'mb-0 shrink-0 peer-has-[[role=menuitem]]/menu-group:block peer-has-[[role=menuitemcheckbox]]/menu-group:block peer-has-[[role=option]]/menu-group:block'
)}
/>

<DropdownMenuPrimitive.Group
ref={ref}
{...props}
className={cn(
'hidden',
'peer/menu-group group/menu-group my-1.5 has-[[role=menuitem]]:block has-[[role=menuitemcheckbox]]:block has-[[role=option]]:block',
props.className
)}
>
{label && <DropdownMenuLabel>{label}</DropdownMenuLabel>}
{props.children}
</DropdownMenuPrimitive.Group>
</>
);
});
export const DropdownMenuGroup = withCn(DropdownMenuPrimitive.Group, 'py-1.5');

export const DropdownMenuPortal = DropdownMenuPrimitive.Portal;

Expand Down
83 changes: 83 additions & 0 deletions src/components/plate-ui/equation-element.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
'use client';

import React, { useRef, useState } from 'react';

import type { TEquationElement } from '@udecode/plate-math';

import { cn, withRef } from '@udecode/cn';
import { useElement } from '@udecode/plate-common/react';
import { useEquationElement } from '@udecode/plate-math/react';
import { RadicalIcon } from 'lucide-react';
import { useSelected } from 'slate-react';

import { EquationPopoverContent } from './equation-popover';
import { PlateElement } from './plate-element';
import { Popover, PopoverTrigger } from './popover';

export const EquationElement = withRef<typeof PlateElement>(
({ children, className, ...props }, ref) => {
const element = useElement<TEquationElement>();

const selected = useSelected();
const [open, setOpen] = useState(selected);
const katexRef = useRef<HTMLDivElement | null>(null);

useEquationElement({
element,
katexRef: katexRef,
options: {
displayMode: true,
errorColor: '#cc0000',
fleqn: false,
leqno: false,
macros: { '\\f': '#1f(#2)' },
output: 'htmlAndMathml',
strict: 'warn',
throwOnError: false,
trust: false,
},
});

return (
<PlateElement
ref={ref}
className={cn('relative my-1', className)}
{...props}
>
<Popover open={open} onOpenChange={setOpen} modal={false}>
<PopoverTrigger asChild>
<div
className={cn(
'group flex cursor-pointer select-none items-center justify-center rounded-sm hover:bg-primary/10 data-[selected=true]:bg-primary/10',
element.texExpression.length === 0
? 'bg-muted p-3 pr-9'
: 'px-2 py-1'
)}
data-selected={selected}
contentEditable={false}
role="button"
>
{element.texExpression.length > 0 ? (
<span ref={katexRef} />
) : (
<div className="flex h-7 w-full items-center gap-2 whitespace-nowrap text-sm text-muted-foreground">
<RadicalIcon className="size-6 text-muted-foreground/80" />
<div>Add a Tex equation</div>
</div>
)}
</div>
</PopoverTrigger>

<EquationPopoverContent
open={open}
placeholder={`f(x) = \\begin{cases}\n x^2, &\\quad x > 0 \\\\\n 0, &\\quad x = 0 \\\\\n -x^2, &\\quad x < 0\n\\end{cases}`}
isInline={false}
setOpen={setOpen}
/>
</Popover>

{children}
</PlateElement>
);
}
);
87 changes: 87 additions & 0 deletions src/components/plate-ui/equation-popover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
'use client';

import React, { useEffect } from 'react';
import TextareaAutosize, {
type TextareaAutosizeProps,
} from 'react-textarea-autosize';

import type { TEquationElement } from '@udecode/plate-math';

import { cn } from '@udecode/cn';
import {
createPrimitiveComponent,
selectSiblingNodePoint,
useEditorRef,
useElement,
} from '@udecode/plate-common/react';
import { useEquationInput } from '@udecode/plate-math/react';
import { BlockSelectionPlugin } from '@udecode/plate-selection/react';
import { CornerDownLeftIcon } from 'lucide-react';
import { useReadOnly, useSelected } from 'slate-react';

import { Button } from './button';
import { PopoverContent } from './popover';

const EquationInput = createPrimitiveComponent(TextareaAutosize)({
propsHook: useEquationInput,
});

const EquationPopoverContent = ({
className,
isInline,
open,
setOpen,
...props
}: {
isInline: boolean;
open: boolean;
setOpen: (open: boolean) => void;
} & TextareaAutosizeProps) => {
const editor = useEditorRef();
const readOnly = useReadOnly();
const element = useElement<TEquationElement>();
const selected = useSelected();

useEffect(() => {
if (isInline && selected) {
setOpen(true);
}
}, [selected, isInline, setOpen]);

if (readOnly) return null;

const onClose = () => {
setOpen(false);

if (isInline) {
selectSiblingNodePoint(editor, { node: element });
} else {
editor
.getApi(BlockSelectionPlugin)
.blockSelection.addSelectedRow(element.id as string);
}
};

return (
<PopoverContent
className="flex gap-2"
onEscapeKeyDown={(e) => {
e.preventDefault();
}}
contentEditable={false}
>
<EquationInput
className={cn('max-h-[50vh] grow resize-none p-2 text-sm', className)}
state={{ isInline, open, onClose }}
autoFocus
{...props}
/>

<Button variant="secondary" className="px-3" onClick={onClose}>
Done <CornerDownLeftIcon className="size-3.5" />
</Button>
</PopoverContent>
);
};

export { EquationPopoverContent };
Loading

0 comments on commit b158825

Please sign in to comment.