diff --git a/.changeset/blue-readers-judge.md b/.changeset/blue-readers-judge.md new file mode 100644 index 0000000000..9ca5eb939c --- /dev/null +++ b/.changeset/blue-readers-judge.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-caption': major +--- + +- Breaking change: the empty caption textarea is no longer showed on image focus. You can use the caption store to show the caption textarea. diff --git a/.changeset/breezy-beers-end.md b/.changeset/breezy-beers-end.md new file mode 100644 index 0000000000..c3aa8961b5 --- /dev/null +++ b/.changeset/breezy-beers-end.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-floating': patch +--- + +Fix: only pop up `floating-toolbar` after the selection is complete. diff --git a/.changeset/four-goats-stare.md b/.changeset/four-goats-stare.md new file mode 100644 index 0000000000..ec78b545d0 --- /dev/null +++ b/.changeset/four-goats-stare.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-font': minor +--- + +Add new transforms `setBlockBackgroundColor`. diff --git a/.changeset/happy-masks-jump.md b/.changeset/happy-masks-jump.md new file mode 100644 index 0000000000..1cfc8d64e6 --- /dev/null +++ b/.changeset/happy-masks-jump.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-layout': minor +--- + +Add `toggleColumns` and fix select all. diff --git a/.changeset/lazy-poets-buy.md b/.changeset/lazy-poets-buy.md new file mode 100644 index 0000000000..9d7ab1809f --- /dev/null +++ b/.changeset/lazy-poets-buy.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-selection': minor +--- + +Add logic for the `block-context-menu` and improved the user experience for `block-selection`, such as interactions related to keyboard shortcuts, bug fixes. diff --git a/.changeset/long-lobsters-judge.md b/.changeset/long-lobsters-judge.md new file mode 100644 index 0000000000..e712d0dc02 --- /dev/null +++ b/.changeset/long-lobsters-judge.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-heading': minor +--- + +Add ToC plugin and sidebar diff --git a/.changeset/many-pillows-unite.md b/.changeset/many-pillows-unite.md new file mode 100644 index 0000000000..27c43f8fe2 --- /dev/null +++ b/.changeset/many-pillows-unite.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-math': minor +--- + +Add `equation` and `inlineEquation` plugins. diff --git a/.changeset/ninety-knives-wash.md b/.changeset/ninety-knives-wash.md new file mode 100644 index 0000000000..f9c2c9bb31 --- /dev/null +++ b/.changeset/ninety-knives-wash.md @@ -0,0 +1,5 @@ +--- +'@udecode/slate-utils': minor +--- + +Add new queries `getAncestorNode` and `getNodesRange` diff --git a/.changeset/pink-yaks-smoke.md b/.changeset/pink-yaks-smoke.md new file mode 100644 index 0000000000..22e9e190d1 --- /dev/null +++ b/.changeset/pink-yaks-smoke.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-dnd': minor +--- + +Add selection after dragging ends. diff --git a/.changeset/smart-flies-relate.md b/.changeset/smart-flies-relate.md new file mode 100644 index 0000000000..ffacb35fd0 --- /dev/null +++ b/.changeset/smart-flies-relate.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-callout': minor +--- + +Add new plugin `callout` diff --git a/.changeset/thin-cycles-itch.md b/.changeset/thin-cycles-itch.md new file mode 100644 index 0000000000..aaa17060b0 --- /dev/null +++ b/.changeset/thin-cycles-itch.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-indent-list': patch +--- + +Add `toggleIndentListByPath`, add `indentList` options diff --git a/.changeset/wicked-cheetahs-laugh.md b/.changeset/wicked-cheetahs-laugh.md new file mode 100644 index 0000000000..c502b83ae2 --- /dev/null +++ b/.changeset/wicked-cheetahs-laugh.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-utils': minor +--- + +Add `addSelectedRow` which depends on `blockSelection` plugin diff --git a/.changeset/wise-pandas-thank.md b/.changeset/wise-pandas-thank.md new file mode 100644 index 0000000000..c2692fc4c6 --- /dev/null +++ b/.changeset/wise-pandas-thank.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-link': patch +--- + +Fix link button closing the floating toolbar. diff --git a/.changeset/yellow-gifts-vanish.md b/.changeset/yellow-gifts-vanish.md new file mode 100644 index 0000000000..474094dd90 --- /dev/null +++ b/.changeset/yellow-gifts-vanish.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-core': patch +--- + +Fix: `toggleNodeType` not working using `at`. diff --git a/.changeset/young-pigs-behave.md b/.changeset/young-pigs-behave.md new file mode 100644 index 0000000000..b4dd34f2ef --- /dev/null +++ b/.changeset/young-pigs-behave.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-media': minor +--- + +Add plugins: `mediaPlaceholder`, `video`,`audio` and `file` diff --git a/.changeset/young-sheep-rush.md b/.changeset/young-sheep-rush.md new file mode 100644 index 0000000000..b29ec61933 --- /dev/null +++ b/.changeset/young-sheep-rush.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-code-block': patch +--- + +Fix select all diff --git a/apps/www/content/docs/components/changelog.mdx b/apps/www/content/docs/components/changelog.mdx index 07c1d6f2b7..6b96a3ce10 100644 --- a/apps/www/content/docs/components/changelog.mdx +++ b/apps/www/content/docs/components/changelog.mdx @@ -8,6 +8,13 @@ Since Plate UI is not a component library, a changelog is maintained here. Use the [CLI](https://platejs.org/docs/components/cli) to install the latest version of the components. +## June 2024 #11 + +### June 6 #11.1 +- feat: `draggable` Add the data-key attribute to facilitate adding selection after the drag-and-drop operation is completed +- breaking change: Add `CaptionProvider` on `image-element` and `media-embed-element`. open the caption by using `CaptionButton` or `useCaptionStore().set.showCaption()` + + ## May 2024 #10 ### May 30 #10.2 diff --git a/apps/www/src/lib/plate/demo/plugins/alignPlugin.ts b/apps/www/src/lib/plate/demo/plugins/alignPlugin.ts index 242531b114..3e68249b5a 100644 --- a/apps/www/src/lib/plate/demo/plugins/alignPlugin.ts +++ b/apps/www/src/lib/plate/demo/plugins/alignPlugin.ts @@ -8,6 +8,7 @@ import { ELEMENT_H5, ELEMENT_H6, } from '@udecode/plate-heading'; +import { ELEMENT_IMAGE } from '@udecode/plate-media'; import { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph'; export const alignPlugin: Partial = { @@ -20,6 +21,7 @@ export const alignPlugin: Partial = { ELEMENT_H3, ELEMENT_H4, ELEMENT_H5, + ELEMENT_IMAGE, ELEMENT_H6, ], }, diff --git a/apps/www/src/registry/default/example/playground-demo.tsx b/apps/www/src/registry/default/example/playground-demo.tsx index bc3648bbd0..56b1e5f81b 100644 --- a/apps/www/src/registry/default/example/playground-demo.tsx +++ b/apps/www/src/registry/default/example/playground-demo.tsx @@ -203,7 +203,10 @@ export const usePlaygroundPlugins = ({ createKbdPlugin({ enabled: !!enabled.kbd }), // Block Style - createAlignPlugin({ ...alignPlugin, enabled: !!enabled.align }), + createAlignPlugin({ + ...alignPlugin, + enabled: !!enabled.align, + }), createIndentPlugin({ enabled: !!enabled.indent, inject: { @@ -269,6 +272,7 @@ export const usePlaygroundPlugins = ({ createBlockSelectionPlugin({ enabled: id === 'blockselection' || !!enabled.blockSelection, options: { + disableContextMenu: true, sizes: { bottom: 0, top: 0, diff --git a/apps/www/src/registry/default/plate-ui/caption.tsx b/apps/www/src/registry/default/plate-ui/caption.tsx index 6ca40e099b..bbd5ec41e1 100644 --- a/apps/www/src/registry/default/plate-ui/caption.tsx +++ b/apps/www/src/registry/default/plate-ui/caption.tsx @@ -1,10 +1,19 @@ -import { cn, withCn, withVariants } from '@udecode/cn'; +import { + cn, + createPrimitiveComponent, + withCn, + withVariants, +} from '@udecode/cn'; import { Caption as CaptionPrimitive, CaptionTextarea as CaptionTextareaPrimitive, + useCaptionButton, + useCaptionButtonState, } from '@udecode/plate-caption'; import { cva } from 'class-variance-authority'; +import { Button } from './button'; + const captionVariants = cva('max-w-full', { defaultVariants: { align: 'center', @@ -30,3 +39,8 @@ export const CaptionTextarea = withCn( 'text-center print:placeholder:text-transparent' ) ); + +export const CaptionButton = createPrimitiveComponent(Button)({ + propsHook: useCaptionButton, + stateHook: useCaptionButtonState, +}); diff --git a/apps/www/src/registry/default/plate-ui/draggable.tsx b/apps/www/src/registry/default/plate-ui/draggable.tsx index 983f3beb0f..88619cf789 100644 --- a/apps/www/src/registry/default/plate-ui/draggable.tsx +++ b/apps/www/src/registry/default/plate-ui/draggable.tsx @@ -2,23 +2,32 @@ import React from 'react'; -import type { - ClassNames, - PlateElementProps, - TEditor, -} from '@udecode/plate-common'; import type { DropTargetMonitor } from 'react-dnd'; import { cn, withRef } from '@udecode/cn'; +import { + type ClassNames, + type PlateElementProps, + type TEditor, + type TElement, + useEditorRef, + useElement, +} from '@udecode/plate-common'; import { type DragItemNode, useDraggable, useDraggableState, } from '@udecode/plate-dnd'; +import { blockSelectionActions } from '@udecode/plate-selection'; import { Icons } from '@/components/icons'; -import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger } from './tooltip'; +import { + Tooltip, + TooltipContent, + TooltipPortal, + TooltipTrigger, +} from './tooltip'; export interface DraggableProps extends PlateElementProps, @@ -68,16 +77,35 @@ export interface DraggableProps ) => boolean; } -const dragHandle = ( - - - - - - Drag to move - - -); +const DragHandle = () => { + const editor = useEditorRef(); + const element = useElement(); + + return ( + + + { + event.stopPropagation(); + event.preventDefault(); + + // if (element.id) { + // blockSelectionActions.addSelectedRow(element.id as string); + // blockContextMenuActions.show(editor.id, event as any); + // } + }} + onMouseDown={() => { + blockSelectionActions.resetSelectedIds(); + }} + /> + + + Drag to move + + + ); +}; export const Draggable = withRef<'div', DraggableProps>( ({ className, classNames = {}, onDropHandler, ...props }, ref) => { @@ -106,7 +134,7 @@ export const Draggable = withRef<'div', DraggableProps>( >
( classNames.blockToolbar )} > -
- {isHovered && dragHandle} +
+ {isHovered && }
diff --git a/apps/www/src/registry/default/plate-ui/floating-toolbar.tsx b/apps/www/src/registry/default/plate-ui/floating-toolbar.tsx index e61a0a1aac..09c412e6fe 100644 --- a/apps/www/src/registry/default/plate-ui/floating-toolbar.tsx +++ b/apps/www/src/registry/default/plate-ui/floating-toolbar.tsx @@ -3,7 +3,12 @@ import React from 'react'; import { cn, withRef } from '@udecode/cn'; -import { PortalBody, useComposedRef } from '@udecode/plate-common'; +import { + PortalBody, + useComposedRef, + useEventEditorSelectors, + usePlateSelectors, +} from '@udecode/plate-common'; import { type FloatingToolbarState, flip, @@ -20,7 +25,12 @@ export const FloatingToolbar = withRef< state?: FloatingToolbarState; } >(({ children, state, ...props }, componentRef) => { + const editorId = usePlateSelectors().id(); + const focusedEditorId = useEventEditorSelectors.focus(); + const floatingToolbarState = useFloatingToolbarState({ + editorId, + focusedEditorId, ...state, floatingOptions: { middleware: [ diff --git a/apps/www/src/registry/default/plate-ui/image-element.tsx b/apps/www/src/registry/default/plate-ui/image-element.tsx index 94e8ecfcad..037a2f0be6 100644 --- a/apps/www/src/registry/default/plate-ui/image-element.tsx +++ b/apps/www/src/registry/default/plate-ui/image-element.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { cn, withRef } from '@udecode/cn'; +import { CaptionProvider } from '@udecode/plate-caption'; import { PlateElement, withHOC } from '@udecode/plate-common'; import { ELEMENT_IMAGE, Image, useMediaState } from '@udecode/plate-media'; import { ResizableProvider, useResizableStore } from '@udecode/plate-resizable'; @@ -14,58 +15,69 @@ import { } from './resizable'; export const ImageElement = withHOC( - ResizableProvider, - withRef( - ({ children, className, nodeProps, ...props }, ref) => { - const { align = 'center', focused, readOnly, selected } = useMediaState(); - const width = useResizableStore().get.width(); + CaptionProvider, + withHOC( + ResizableProvider, + withRef( + ({ children, className, nodeProps, ...props }, ref) => { + const { + align = 'center', + focused, + readOnly, + selected, + } = useMediaState(); - return ( - - -
- - - - - + const width = useResizableStore().get.width(); - - - -
+ return ( + + +
+ + + + + - {children} - - - ); - } + + + +
+ + {children} +
+
+ ); + } + ) ) ); diff --git a/apps/www/src/registry/default/plate-ui/media-embed-element.tsx b/apps/www/src/registry/default/plate-ui/media-embed-element.tsx index 1f3f0f1950..86aebf62f7 100644 --- a/apps/www/src/registry/default/plate-ui/media-embed-element.tsx +++ b/apps/www/src/registry/default/plate-ui/media-embed-element.tsx @@ -3,6 +3,7 @@ import LiteYouTubeEmbed from 'react-lite-youtube-embed'; import { Tweet } from 'react-tweet'; import { cn, withRef } from '@udecode/cn'; +import { CaptionProvider } from '@udecode/plate-caption'; import { PlateElement, withHOC } from '@udecode/plate-common'; import { ELEMENT_MEDIA_EMBED, @@ -21,117 +22,125 @@ import { } from './resizable'; export const MediaEmbedElement = withHOC( - ResizableProvider, - withRef(({ children, className, ...props }, ref) => { - const { - align = 'center', - embed, - focused, - isTweet, - isVideo, - isYoutube, - readOnly, - selected, - } = useMediaState({ - urlParsers: [parseTwitterUrl, parseVideoUrl], - }); - const width = useResizableStore().get.width(); - const provider = embed?.provider; + CaptionProvider, + withHOC( + ResizableProvider, + withRef(({ children, className, ...props }, ref) => { + const { + align = 'center', + embed, + focused, + isTweet, + isVideo, + isYoutube, + readOnly, + selected, + } = useMediaState({ + urlParsers: [parseTwitterUrl, parseVideoUrl], + }); + const width = useResizableStore().get.width(); + const provider = embed?.provider; - return ( - - -
- + +
- + + - {isVideo ? ( - isYoutube ? ( - _iframe]:absolute [&_>_iframe]:left-0 [&_>_iframe]:top-0 [&_>_iframe]:size-full', - '[&_>_.lty-playbtn]:z-[1] [&_>_.lty-playbtn]:h-[46px] [&_>_.lty-playbtn]:w-[70px] [&_>_.lty-playbtn]:rounded-[14%] [&_>_.lty-playbtn]:bg-[#212121] [&_>_.lty-playbtn]:opacity-80 [&_>_.lty-playbtn]:[transition:all_0.2s_cubic-bezier(0,_0,_0.2,_1)]', - '[&:hover_>_.lty-playbtn]:bg-[red] [&:hover_>_.lty-playbtn]:opacity-100', - '[&_>_.lty-playbtn]:before:border-y-[11px] [&_>_.lty-playbtn]:before:border-l-[19px] [&_>_.lty-playbtn]:before:border-r-0 [&_>_.lty-playbtn]:before:border-[transparent_transparent_transparent_#fff] [&_>_.lty-playbtn]:before:content-[""]', - '[&_>_.lty-playbtn]:absolute [&_>_.lty-playbtn]:left-1/2 [&_>_.lty-playbtn]:top-1/2 [&_>_.lty-playbtn]:[transform:translate3d(-50%,-50%,0)]', - '[&_>_.lty-playbtn]:before:absolute [&_>_.lty-playbtn]:before:left-1/2 [&_>_.lty-playbtn]:before:top-1/2 [&_>_.lty-playbtn]:before:[transform:translate3d(-50%,-50%,0)]', - '[&.lyt-activated]:cursor-[unset]', - '[&.lyt-activated]:before:pointer-events-none [&.lyt-activated]:before:opacity-0', - '[&.lyt-activated_>_.lty-playbtn]:pointer-events-none [&.lyt-activated_>_.lty-playbtn]:!opacity-0' - )} - /> - ) : ( + {isVideo ? ( + isYoutube ? ( + _iframe]:absolute [&_>_iframe]:left-0 [&_>_iframe]:top-0 [&_>_iframe]:size-full', + '[&_>_.lty-playbtn]:z-[1] [&_>_.lty-playbtn]:h-[46px] [&_>_.lty-playbtn]:w-[70px] [&_>_.lty-playbtn]:rounded-[14%] [&_>_.lty-playbtn]:bg-[#212121] [&_>_.lty-playbtn]:opacity-80 [&_>_.lty-playbtn]:[transition:all_0.2s_cubic-bezier(0,_0,_0.2,_1)]', + '[&:hover_>_.lty-playbtn]:bg-[red] [&:hover_>_.lty-playbtn]:opacity-100', + '[&_>_.lty-playbtn]:before:border-y-[11px] [&_>_.lty-playbtn]:before:border-l-[19px] [&_>_.lty-playbtn]:before:border-r-0 [&_>_.lty-playbtn]:before:border-[transparent_transparent_transparent_#fff] [&_>_.lty-playbtn]:before:content-[""]', + '[&_>_.lty-playbtn]:absolute [&_>_.lty-playbtn]:left-1/2 [&_>_.lty-playbtn]:top-1/2 [&_>_.lty-playbtn]:[transform:translate3d(-50%,-50%,0)]', + '[&_>_.lty-playbtn]:before:absolute [&_>_.lty-playbtn]:before:left-1/2 [&_>_.lty-playbtn]:before:top-1/2 [&_>_.lty-playbtn]:before:[transform:translate3d(-50%,-50%,0)]', + '[&.lyt-activated]:cursor-[unset]', + '[&.lyt-activated]:before:pointer-events-none [&.lyt-activated]:before:opacity-0', + '[&.lyt-activated_>_.lty-playbtn]:pointer-events-none [&.lyt-activated_>_.lty-playbtn]:!opacity-0' + )} + /> + ) : ( +
+