Skip to content

Commit

Permalink
Merge pull request #4010 from udecode/feat/dnd-row
Browse files Browse the repository at this point in the history
Table row dnd
  • Loading branch information
zbeyens authored Jan 21, 2025
2 parents 6ac5b71 + 9db0ded commit 421fd33
Show file tree
Hide file tree
Showing 37 changed files with 689 additions and 259 deletions.
12 changes: 12 additions & 0 deletions .changeset/loud-ties-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@udecode/plate-selection': patch
---

- Block selection area: prevent selecting selectable descendants
- `editor.api.blockSelection`:
- Add `add`, `clear`, `delete`, `deselect`, `has`, `set`
- Deprecate `addSelectedRow`, use `add` instead
- Deprecate `unselect`, use `deselect` instead
- Deprecate `resetSelectedIds`, use `clear` instead
- `selectedAll` -> `selectAll`
- Deprecate `data-plate-prevent-unselect`, use `data-plate-prevent-deselect` instead
5 changes: 5 additions & 0 deletions .changeset/neat-lizards-brush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@udecode/plate-table': patch
---

- Recompute cell indices when moving node in table
5 changes: 5 additions & 0 deletions .changeset/swift-files-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@udecode/plate-dnd': patch
---

- `useDndNode`: `onDropHandler` can return `void`
82 changes: 47 additions & 35 deletions apps/www/content/docs/en/block-selection.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ BlockSelectionPlugin.configure({
speedDivider: 1.5,
},
// The distance needed to move for the selection area to appear.
// If its too small, it may cause the mouse click event to be blocked. 10 is a good default.
// If it's too small, it may cause the mouse click event to be blocked. 10 is a good default.
startThreshold: 4,
},
},
Expand Down Expand Up @@ -145,14 +145,14 @@ There are two ways to handle resetting selection across the full page:
1. Direct API call:
```tsx
editor.api.blockSelection.unselect();
editor.api.blockSelection.deselect();
```
2. Click outside handler:
```tsx
const handleClickOutside = (event: MouseEvent) => {
if (!(event.target as HTMLElement).closest('[data-plate-selectable]')) {
editor.api.blockSelection.unselect();
editor.api.blockSelection.deselect();
}
};
```
Expand Down Expand Up @@ -240,27 +240,38 @@ Function to determine if a block element is selectable.
## API
### editor.api.blockSelection.focus
Focuses the block selection shadow input. This input handles copy, delete, and paste events for selected blocks.
### editor.api.blockSelection.addSelectedRow
### editor.api.blockSelection.add
Adds a selected row to the block selection.
Adds one or more blocks to the selection.
<APIParameters>
<APIItem name="id" type="string">
The ID of the row to be selected.
<APIItem name="id" type="string | string[]">
The ID(s) of the block(s) to be selected.
</APIItem>
<APIItem name="options" type="object" optional>
<APISubList>
<APISubListItem parent="options" name="clear" type="boolean" optional>
Whether to clear existing selections before adding the new one.
- **Default:** `true`
</APISubListItem>
</APISubList>
</APIParameters>
### editor.api.blockSelection.clear
Resets the set of selected IDs to an empty set.
### editor.api.blockSelection.delete
Removes one or more blocks from the selection.
<APIParameters>
<APIItem name="id" type="string | string[]">
The ID(s) of the block(s) to remove from selection.
</APIItem>
</APIParameters>
### editor.api.blockSelection.deselect
Deselects all blocks and sets the `isSelecting` flag to false.
### editor.api.blockSelection.focus
Focuses the block selection shadow input. This input handles copy, delete, and paste events for selected blocks.
### editor.api.blockSelection.getNodes
Gets the selected blocks in the editor.
Expand All @@ -271,35 +282,36 @@ Gets the selected blocks in the editor.
</APIItem>
</APIReturns>
### editor.api.blockSelection.resetSelectedIds
### editor.api.blockSelection.has
Resets the set of selected IDs to an empty set.
Checks if one or more blocks are selected.
### editor.api.blockSelection.selectedAll
<APIParameters>
<APIItem name="id" type="string | string[]">
The ID(s) of the block(s) to check.
</APIItem>
</APIParameters>
<APIReturns>
<APIItem type="boolean">
Returns true if all specified blocks are selected.
</APIItem>
</APIReturns>
### editor.api.blockSelection.selectAll
Selects all selectable blocks in the editor.
### editor.api.blockSelection.setSelectedIds
### editor.api.blockSelection.set
Sets the selected IDs based on added and removed elements.
Sets the selection to one or more blocks, clearing any existing selection.
<APIParameters>
<APIItem name="options" type="ChangedElements">
<APISubList>
<APISubListItem parent="options" name="added" type="HTMLElement[]">
Array of HTML elements to be added to the selection.
</APISubListItem>
<APISubListItem parent="options" name="removed" type="HTMLElement[]">
Array of HTML elements to be removed from the selection.
</APISubListItem>
</APISubList>
<APIItem name="id" type="string | string[]">
The ID(s) of the block(s) to be selected.
</APIItem>
</APIParameters>
### editor.api.blockSelection.unselect
Unselects all blocks and sets the `isSelecting` flag to false.
## Transforms
### editor.tf.blockSelection.duplicate
Expand Down
17 changes: 17 additions & 0 deletions apps/www/content/docs/en/components/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,23 @@ Use the [CLI](https://platejs.org/docs/components/cli) to install the latest ver

## January 2025 #18

### January 21 #18.7

- `table-row-element`: support row dnd
- `editor`: z-50 for selection area
- `draggable`:
- Replace `editor.api.blockSelection.replaceSelectedIds` with `editor.api.blockSelection.clear`
- Use `TooltipButton` for drag handle
- Block select on drag handle click
- Hide drag handle in table cells
- `column-element`, `table-cell-element`: add `isSelectionAreaVisible` check
- `block-selection`: hide if dragging
- Replace `editor.api.blockSelection.addSelectedRow` with `editor.api.blockSelection.set`:
- `ai-menu`
- `equation-popover`



### January 18 #18.6

- `inline-equation-element` and `equation-popover`: Fix: When selecting an inline equation, the popover should not open, as it causes the selection to be lost.
Expand Down
4 changes: 2 additions & 2 deletions apps/www/content/docs/en/form.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function RHFEditorForm() {

const onSubmit = (data: FormData) => {
// data.content will have final editor content
console.log('Submitted:', data.content);
console.info('Submitted:', data.content);
};

return (
Expand Down Expand Up @@ -110,7 +110,7 @@ export function EditorForm() {
const editor = usePlateEditor();

const onSubmit = (data: FormValues) => {
console.log('Submitted data:', data.content);
console.info('Submitted data:', data.content);
};

return (
Expand Down
2 changes: 1 addition & 1 deletion apps/www/content/docs/en/plate-static.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ const html = await serializeHtml(editor, {
props: { className: 'max-w-3xl mx-auto' },
});

console.log(html);
console.info(html);
/*
<div data-slate-editor="true" data-slate-node="value" class="max-w-3xl mx-auto">
<div data-slate-node="element" data-slate-type="p" ...>Hello Plate!</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/registry/default/plate-ui/ai-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function AIMenu() {
if (!editor.api.isAt({ end: true }) && !editor.api.isEmpty(ancestor)) {
editor
.getApi(BlockSelectionPlugin)
.blockSelection.addSelectedRow(ancestor.id as string);
.blockSelection.set(ancestor.id as string);
}

show(editor.api.toDOMNode(ancestor)!);
Expand Down
6 changes: 5 additions & 1 deletion apps/www/src/registry/default/plate-ui/block-selection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import React from 'react';

import { cn } from '@udecode/cn';
import { useEditorPlugin } from '@udecode/plate-core/react';
import { DndPlugin } from '@udecode/plate-dnd';
import { useBlockSelected } from '@udecode/plate-selection/react';
import { type VariantProps, cva } from 'class-variance-authority';

Expand All @@ -27,14 +29,16 @@ export function BlockSelection({
}: React.HTMLAttributes<HTMLDivElement> &
VariantProps<typeof blockSelectionVariants>) {
const isBlockSelected = useBlockSelected();
const { useOption } = useEditorPlugin(DndPlugin);
const isDragging = useOption('isDragging');

if (!isBlockSelected) return null;

return (
<div
className={cn(
blockSelectionVariants({
active: isBlockSelected,
active: isBlockSelected && !isDragging,
}),
className
)}
Expand Down
32 changes: 20 additions & 12 deletions apps/www/src/registry/default/plate-ui/column-element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { PathApi } from '@udecode/plate';
import { useReadOnly, withHOC } from '@udecode/plate/react';
import { useDraggable, useDropLine } from '@udecode/plate-dnd';
import { ResizableProvider } from '@udecode/plate-resizable';
import { BlockSelectionPlugin } from '@udecode/plate-selection/react';
import { GripHorizontal } from 'lucide-react';

import { Button } from './button';
Expand All @@ -24,8 +25,12 @@ import {
export const ColumnElement = withHOC(
ResizableProvider,
withRef<typeof PlateElement>(({ children, className, ...props }, ref) => {
const readOnly = useReadOnly();
const { width } = props.element as TColumnElement;
const readOnly = useReadOnly();
const isSelectionAreaVisible = props.editor.useOption(
BlockSelectionPlugin,
'isSelectionAreaVisible'
);

const { isDragging, previewRef, handleRef } = useDraggable({
canDropNode: ({ dragEntry, dropEntry }) =>
Expand All @@ -40,16 +45,18 @@ export const ColumnElement = withHOC(

return (
<div className="group/column relative" style={{ width: width ?? '100%' }}>
<div
ref={handleRef}
className={cn(
'absolute left-1/2 top-2 z-50 -translate-x-1/2 -translate-y-1/2',
'pointer-events-auto flex items-center',
'opacity-0 transition-opacity group-hover/column:opacity-100'
)}
>
<ColumnDragHandle />
</div>
{!readOnly && !isSelectionAreaVisible && (
<div
ref={handleRef}
className={cn(
'absolute left-1/2 top-2 z-50 -translate-x-1/2 -translate-y-1/2',
'pointer-events-auto flex items-center',
'opacity-0 transition-opacity group-hover/column:opacity-100'
)}
>
<ColumnDragHandle />
</div>
)}

<PlateElement
ref={useComposedRef(ref, previewRef)}
Expand All @@ -67,7 +74,8 @@ export const ColumnElement = withHOC(
)}
>
{children}
<DropLine />

{!readOnly && !isSelectionAreaVisible && <DropLine />}
</div>
</PlateElement>
</div>
Expand Down
Loading

0 comments on commit 421fd33

Please sign in to comment.