Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
felixfeng33 committed Nov 7, 2024
1 parent 0b9be46 commit 78c873f
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 38 deletions.
13 changes: 8 additions & 5 deletions apps/www/content/docs/block-selection.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,15 @@ export function BlockSelection() {

This component should be rendered inside each block element for consistent selection feedback. Plate UI is doing it in `plate-element.tsx`.

### Disable browser default scroll behavior
## Prevent unselect

When selecting text and moving the cursor to the bottom of the page, the browser's default scroll behavior can conflict with the `BlockSelectionPlugin`. To mitigate this, you can add a non-selectable area to the right side of the editor:
To prevent unselecting blocks when clicking on certain elements, add the `data-plate-prevent-unselect` attribute to those components

For example:
```tsx
<div className="absolute right-0 top-0 h-full w-4 select-none" />
<YourSpecialButtoon data-plate-prevent-unselect />
```

This helps prevent unexpected scrolling during selection operations.

## Plugins

### BlockSelectionPlugin
Expand Down Expand Up @@ -232,6 +231,10 @@ A set of IDs for the currently selected blocks.

## 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

Adds a selected row to the block selection.
Expand Down
5 changes: 5 additions & 0 deletions apps/www/content/docs/components/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ Use the [CLI](https://platejs.org/docs/components/cli) to install the latest ver

## November 2024 #16

### November 7 #16.4

- `block-context-menu`: prevent unselect when clicking on the context menu
- `block-selection`: Add `editor.getApi(BlockSelectionPlugin).blockSelection.focus()` in onCloseAutoFocus.

### November 6 #16.3

- `editor`: add `overflow-x-hidden` to prevent horizontal scrolling
Expand Down
13 changes: 12 additions & 1 deletion apps/www/src/registry/default/plate-ui/block-context-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,17 @@ export function BlockContextMenu({ children }: { children: React.ReactNode }) {
);

return (
<ContextMenu modal={false}>
<ContextMenu
onOpenChange={(open) => {
if (!open) {
// prevent unselect the block selection
setTimeout(() => {
api.blockMenu.hide();
}, 0);
}
}}
modal={false}
>
<ContextMenuTrigger
asChild
onContextMenu={(event) => {
Expand All @@ -83,6 +93,7 @@ export function BlockContextMenu({ children }: { children: React.ReactNode }) {
className="w-64"
onCloseAutoFocus={(e) => {
e.preventDefault();
editor.getApi(BlockSelectionPlugin).blockSelection.focus();

if (value === 'askAI') {
editor.getApi(AIChatPlugin).aiChat.show();
Expand Down
2 changes: 1 addition & 1 deletion packages/selection/src/react/BlockMenuPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const BlockMenuPlugin = createTPlatePlugin<BlockMenuConfig>({
handlers: {
onMouseDown: ({ event, getOptions }) => {
if (event.button === 0 && getOptions().openId) {
// event.preventDefault();
event.preventDefault();
api.blockMenu.hide();
}
if (event.button === 2) event.preventDefault();
Expand Down
32 changes: 28 additions & 4 deletions packages/selection/src/react/BlockSelectionPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ import {
} from './transforms/setBlockSelectionNodes';
import {
copySelectedBlocks,
onChangeBlockSelection,
pasteSelectedBlocks,
selectInsertedBlocks,
} from './utils';
Expand All @@ -62,6 +61,7 @@ export type BlockSelectionConfig = PluginConfig<
query?: QueryNodeOptions;
rightSelectionAreaClassName?: string;
selectedIds?: Set<string>;
shadowInputRef?: React.RefObject<HTMLInputElement>;
onKeyDownSelecting?: (e: KeyboardEvent) => void;
} & BlockSelectionSelectors,
{
Expand All @@ -82,6 +82,7 @@ export type BlockSelectionApi = {
setSelectedIds: (
options: Partial<ChangedElements> & { ids?: string[] }
) => void;
focus: () => void;
getNodes: () => TNodeEntry[];
resetSelectedIds: () => void;
selectedAll: () => void;
Expand All @@ -90,7 +91,7 @@ export type BlockSelectionApi = {

export const BlockSelectionAfterEditable: EditableSiblingComponent = () => {
const editor = useEditorRef();
const { api, getOption, getOptions, useOption } =
const { api, getOption, getOptions, setOption, useOption } =
useEditorPlugin<BlockSelectionConfig>({ key: 'blockSelection' });
const isSelecting = useOption('isSelecting');
const selectedIds = useOption('selectedIds');
Expand All @@ -102,11 +103,12 @@ export const BlockSelectionAfterEditable: EditableSiblingComponent = () => {

React.useEffect(() => {
setIsMounted(true);
setOption('shadowInputRef', inputRef);

return () => {
setIsMounted(false);
};
}, []);
}, [setOption]);

React.useEffect(() => {
if (isSelecting && inputRef.current) {
Expand Down Expand Up @@ -278,6 +280,7 @@ export const BlockSelectionPlugin = createTPlatePlugin<BlockSelectionConfig>({
maxLevel: 1,
},
selectedIds: new Set(),
shadowInputRef: { current: null },
},
plugins: [BlockMenuPlugin],
render: {
Expand All @@ -293,8 +296,22 @@ export const BlockSelectionPlugin = createTPlatePlugin<BlockSelectionConfig>({
afterEditable: BlockSelectionAfterEditable,
},
handlers: {
onChange: onChangeBlockSelection,
onKeyDown: onKeyDownSelection,
onMouseDown: ({ api, editor, event, getOptions }) => {
const target = event.target as HTMLElement;

if (target.dataset.platePreventUnselect) return;

console.log(editor.getOption(BlockMenuPlugin, 'openId'), 'fj');

if (
event.button === 0 &&
getOptions().selectedIds!.size > 0 &&
!editor.getOption(BlockMenuPlugin, 'openId')
) {
api.blockSelection.unselect();
}
},
},
})
.extendOptions(({ getOptions }) => ({
Expand All @@ -303,6 +320,13 @@ export const BlockSelectionPlugin = createTPlatePlugin<BlockSelectionConfig>({
}))
.extendApi<Partial<BlockSelectionApi>>(
({ editor, getOption, getOptions, setOption }) => ({
focus: () => {
const shadowInputRef = getOption('shadowInputRef');

if (shadowInputRef?.current) {
shadowInputRef.current.focus({ preventScroll: true });
}
},
getNodes: () => {
const selectedIds = getOption('selectedIds');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export const duplicateBlockSelectionNodes = (
})
.filter(Boolean);

const api = editor.getApi(BlockSelectionPlugin);

setTimeout(() => {
editor
.getApi(BlockSelectionPlugin)
.blockSelection.setSelectedIds({ ids } as any);
api.blockSelection.setSelectedIds({ ids } as any);
}, 0);
};
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ export const setBlockSelectionIndent = (
indent: number,
options?: SetNodesOptions
) => {
const api = editor.getApi(BlockSelectionPlugin);

withoutNormalizing(editor, () => {
const blocks = editor
.getApi(BlockSelectionPlugin)
.blockSelection.getNodes();
const blocks = api.blockSelection.getNodes();

blocks.forEach(([node, path]) => {
const prevIndent = (node as any).indent ?? 0;
Expand Down
1 change: 0 additions & 1 deletion packages/selection/src/react/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@
*/

export * from './copySelectedBlocks';
export * from './onChangeBlockSelection';
export * from './pasteSelectedBlocks';
export * from './selectInsertedBlocks';
20 changes: 0 additions & 20 deletions packages/selection/src/react/utils/onChangeBlockSelection.ts

This file was deleted.

0 comments on commit 78c873f

Please sign in to comment.