๐Ÿ“ Sign Up | ๐Ÿ” Log In

โ† Root | โ†‘ Up

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ๐Ÿ“„ shadcn/directory/udecode/plate/(plugins)/(functionality)/dnd.cn โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘

title: ๆ‹–ๆ‹ฝๅŠŸ่ƒฝ description: ้€š่ฟ‡ๆ‹–ๆ‹ฝๅŒบๅ—ๆฅ้‡ๆ–ฐ็ป„็ป‡็ผ–่พ‘ๅ™จไธญ็š„ๅ†…ๅฎนใ€‚ docs:

  • route: /docs/components/block-draggable title: ๅฏๆ‹–ๆ‹ฝๅŒบๅ—็ป„ไปถ

<ComponentPreview name="dnd-demo" /> <PackageInfo>

ๅŠŸ่ƒฝ็‰นๆ€ง

  • ้€š่ฟ‡ๆ‹–ๆ‹ฝๅŒบๅ—ๅฎž็Žฐๅ†…ๅฎน็งปๅŠจๅ’Œๆ’ๅ…ฅ
  • ๆ‹–ๆ‹ฝ่‡ณ่ง†็ช—่พน็ผ˜ๆ—ถ่‡ชๅŠจๆปšๅŠจ
  • ๆ”ฏๆŒๆ–‡ไปถๆ‹–ๆ”พๆ’ๅ…ฅๅช’ไฝ“ๅŒบๅ—
  • ๅฏ่ง†ๅŒ–ๆ‹–ๆ”พๆŒ‡็คบๅ™จๅ’Œๆ‹–ๆ‹ฝๆ‰‹ๆŸ„
</PackageInfo>

ๅฅ—ไปถไฝฟ็”จ

<Steps>

ๅฎ‰่ฃ…

ๆœ€ๅฟซๆท็š„ๆ–นๅผๆ˜ฏไฝฟ็”จ DndKit ๅฅ—ไปถ๏ผŒๅฎƒๅŒ…ๅซ้ข„้…็ฝฎ็š„ DndPluginใ€React DnD ่ฎพ็ฝฎไปฅๅŠ BlockDraggable UI็ป„ไปถใ€‚

<ComponentSource name="dnd-kit" />
  • BlockDraggable: ไธบๅŒบๅ—ๆธฒๆŸ“ๆ‹–ๆ‹ฝๆ‰‹ๆŸ„ๅ’Œๆ”พ็ฝฎๆŒ‡็คบๅ™จ

ๆทปๅŠ ๅฅ—ไปถ

import { createPlateEditor } from 'platejs/react';
import { DndKit } from '@/components/editor/plugins/dnd-kit';

const editor = createPlateEditor({
  plugins: [
    // ...ๅ…ถไป–ๆ’ไปถ
    ...DndKit,
  ],
});
</Steps>

ๆ‰‹ๅŠจ้…็ฝฎ

<Steps>

ๅฎ‰่ฃ…ไพ่ต–

npm install @platejs/dnd react-dnd react-dnd-html5-backend

ๆทปๅŠ ๆ’ไปถ

import { DndPlugin } from '@platejs/dnd';
import { createPlateEditor } from 'platejs/react';

const editor = createPlateEditor({
  plugins: [
    // ...ๅ…ถไป–ๆ’ไปถ
    DndPlugin,
  ],
});

้…็ฝฎๆ’ไปถ

้€š่ฟ‡ๅฏๆ‹–ๆ‹ฝ็ป„ไปถๅ’ŒDnD provider้…็ฝฎๆ‹–ๆ”พๅŠŸ่ƒฝ๏ผš

import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { DndPlugin } from '@platejs/dnd';

DndPlugin.configure({
  render: {
    aboveSlate: ({ children }) => (
      <DndProvider backend={HTML5Backend}>{children}</DndProvider>
    ),
  },
});
  • render.aboveNodes: ๅˆ†้… BlockDraggable ็ป„ไปถๅœจๅŒบๅ—ไธŠๆ–นๆธฒๆŸ“ๆ‹–ๆ‹ฝๆ‰‹ๆŸ„
  • render.aboveSlate: ็”จ DndProvider ๅŒ…่ฃน็ผ–่พ‘ๅ™จใ€‚ๅฆ‚ๆžœReactๆ ‘ไธญๅทฒๆœ‰ DndProvider ๅฏ็งป้™คๆญค้…็ฝฎ

้ซ˜็บง้…็ฝฎ

ๆทปๅŠ ่‡ชๅŠจๆปšๅŠจๅ’Œๆ–‡ไปถๆ‹–ๆ”พๅค„็†๏ผš

import { DndPlugin } from '@platejs/dnd';
import { PlaceholderPlugin } from '@platejs/media/react';

DndPlugin.configure({
  options: {
    enableScroller: true,
    onDropFiles: ({ dragItem, editor, target }) => {
      editor
        .getTransforms(PlaceholderPlugin)
        .insert.media(dragItem.files, { at: target, nextBlock: false });
    },
  },
  render: {
    aboveNodes: BlockDraggable,
    aboveSlate: ({ children }) => (
      <DndProvider backend={HTML5Backend}>{children}</DndProvider>
    ),
  },
});
  • enableScroller: ๅฏ็”จๆ‹–ๆ‹ฝ่‡ณ่ง†็ช—่พน็ผ˜ๆ—ถ็š„่‡ชๅŠจๆปšๅŠจ
  • onDropFiles: ๅค„็†ๆ–‡ไปถๆ‹–ๆ”พ๏ผŒๅœจ็›ฎๆ ‡ไฝ็ฝฎๆ’ๅ…ฅๅช’ไฝ“ๅŒบๅ—
</Steps>

ๆ’ไปถ

DndPlugin

ๅฎž็Žฐ็ผ–่พ‘ๅ™จๅ†…ๆ‹–ๆ‹ฝๅŠŸ่ƒฝ็š„ๆ’ไปถใ€‚

<API name="DndPlugin"> <APIOptions> <APIItem name="enableScroller" type="boolean" optional> ๆ˜ฏๅฆๅฏ็”จๆ‹–ๆ‹ฝ่‡ณ่ง†็ช—่พน็ผ˜่‡ชๅŠจๆปšๅŠจ - **้ป˜่ฎคๅ€ผ:** `false` </APIItem> <APIItem name="scrollerProps" type="Partial<ScrollerProps>" optional> ๅฝ“ๅฏ็”จๆปšๅŠจๆ—ถ็š„ `Scroller` ็ป„ไปถๅฑžๆ€ง </APIItem> <APIItem name="onDropFiles" type="function" optional> ๆ–‡ไปถๆ‹–ๆ”พไบ‹ไปถๅค„็†ๅ™จ <APISubList> <APISubListItem parent="onDropFiles" name="id" type="string"> ็›ฎๆ ‡ๅ…ƒ็ด ID </APISubListItem> <APISubListItem parent="onDropFiles" name="dragItem" type="FileDragItemNode"> ๅŒ…ๅซๆ‹–ๆ”พๆ–‡ไปถ็š„ๅฏน่ฑก </APISubListItem> <APISubListItem parent="onDropFiles" name="editor" type="PlateEditor"> ็ผ–่พ‘ๅ™จๅฎžไพ‹ </APISubListItem> <APISubListItem parent="onDropFiles" name="target" type="Path"> ๆ–‡ไปถๅบ”ๆ’ๅ…ฅ็š„่ทฏๅพ„ </APISubListItem> </APISubList> </APIItem> <APIItem name="dropTarget" type="{ id: string | null; line: DropLineDirection }" optional> ๅฝ“ๅ‰ๆ‹–ๆ”พ็›ฎๆ ‡็Šถๆ€๏ผŒๅŒ…ๅซ็›ฎๆ ‡ๅ…ƒ็ด IDๅ’Œๆ”พ็ฝฎ็บฟๆ–นๅ‘ </APIItem> </APIOptions> </API>

API

focusBlockStartById

้€š่ฟ‡ID้€‰ไธญๅŒบๅ—่ตทๅง‹ไฝ็ฝฎๅนถ่š็„ฆ็ผ–่พ‘ๅ™จใ€‚

<API name="focusBlockStartById"> <APIParameters> <APIItem name="id" type="string"> ่ฆ่š็„ฆ็š„ๅŒบๅ—ID </APIItem> </APIParameters> </API>

getBlocksWithId

่ฟ”ๅ›žๅธฆๆœ‰ID็š„ๅŒบๅ—ๆ•ฐ็ป„ใ€‚

<API name="getBlocksWithId"> <APIOptions type="EditorNodesOptions"> ่Žทๅ–่Š‚็‚นๆก็›ฎ็š„้€‰้กน </APIOptions> <APIReturns type="NodeEntry[]"> ๅธฆๆœ‰ID็š„ๅŒบๅ—ๆ•ฐ็ป„ </APIReturns> </API>

selectBlockById

้€š่ฟ‡ID้€‰ไธญๅŒบๅ—ใ€‚

<API name="selectBlockById"> <APIParameters> <APIItem name="id" type="string"> ่ฆ้€‰ไธญ็š„ๅŒบๅ—ID </APIItem> </APIParameters> </API>

้’ฉๅญ

useDndNode

็ป„ๅˆไบ† useDragNode ๅ’Œ useDropNode ็š„่‡ชๅฎšไน‰้’ฉๅญ๏ผŒ็”จไบŽๅฏ็”จ็ผ–่พ‘ๅ™จ่Š‚็‚น็š„ๆ‹–ๆ‹ฝๅŠŸ่ƒฝใ€‚ๆไพ›้ป˜่ฎค็š„ๆ‹–ๆ‹ฝ้ข„่งˆๆ•ˆๆžœ๏ผŒๅฏ่‡ชๅฎšไน‰ๆˆ–็ฆ็”จใ€‚

<API name="useDndNode"> <APIOptions type="UseDndNodeOptions"> <APIItem name="element" type="TElement"> ่ฆๆ‹–ๆ‹ฝ็š„่Š‚็‚น </APIItem> <APIItem name="type" type="string" optional> ๆ‹–ๆ‹ฝ้กน็ฑปๅž‹ - **้ป˜่ฎคๅ€ผ:** `'block'` </APIItem> <APIItem name="nodeRef" type="any"> ่Š‚็‚นๆ‹–ๆ‹ฝๅผ•็”จ </APIItem> <APIItem name="orientation" type="'horizontal' | 'vertical'" optional> ๆ‹–ๆ‹ฝๆ–นๅ‘ - **้ป˜่ฎคๅ€ผ:** `'vertical'` </APIItem> <APIItem name="canDropNode" type="(args: { dragEntry: NodeEntry; dragItem: DragItemNode; dropEntry: NodeEntry; editor: PlateEditor }) => boolean" optional> ๅˆคๆ–ญ่Š‚็‚น่ƒฝๅฆๆ”พ็ฝฎๅˆฐๅฝ“ๅ‰ไฝ็ฝฎ็š„ๅ›ž่ฐƒ </APIItem> <APIItem name="preview" type="previewOptions" optional> ๆ‹–ๆ‹ฝ่Š‚็‚น็š„้ข„่งˆ้€‰้กน </APIItem> <APIItem name="drag" type="dragOptions" optional> ๆ‹–ๆ‹ฝ่Š‚็‚น็š„ๆ‹–ๆ‹ฝ้€‰้กน </APIItem> <APIItem name="drop" type="dropOptions" optional> ๆ‹–ๆ‹ฝ่Š‚็‚น็š„ๆ”พ็ฝฎ้€‰้กน </APIItem> <APIItem name="onDropHandler" type="string" optional> ่Š‚็‚นๆ”พ็ฝฎๆ—ถ็š„ๅค„็†ๅ‡ฝๆ•ฐ </APIItem> </APIOptions> <APIReturns type="object"> <APIItem name="isDragging" type="boolean"> ่Š‚็‚นๆ˜ฏๅฆๆญฃๅœจ่ขซๆ‹–ๆ‹ฝ </APIItem> <APIItem name="isOver" type="boolean"> ๆ‹–ๆ‹ฝ่Š‚็‚นๆ˜ฏๅฆๅœจๆ”พ็ฝฎ็›ฎๆ ‡ไธŠๆ–น </APIItem> <APIItem name="dragRef" type="ConnectDragSource"> ๅฏๆ‹–ๆ‹ฝๅ…ƒ็ด ็š„ๆ‹–ๆ‹ฝๅผ•็”จ </APIItem> </APIReturns> </API>

useDragNode

ไฝฟ็”จ react-dnd ็š„ useDrag ้’ฉๅญๅฎž็Žฐ่Š‚็‚นๆ‹–ๆ‹ฝๅŠŸ่ƒฝ็š„่‡ชๅฎšไน‰้’ฉๅญใ€‚

<API name="useDragNode"> <APIOptions type="UseDragNodeOptions"> <APIItem name="element" type="TElement"> ่ฆๆ‹–ๆ‹ฝ็š„่Š‚็‚น </APIItem> <APIItem name="item" type="DragObject | DragObjectFactory<DragObject>" optional> ๆ‹–ๆ‹ฝๅฏน่ฑกๆˆ–ๅ…ถๅทฅๅŽ‚ๅ‡ฝๆ•ฐ </APIItem> </APIOptions> </API>

useDraggable

ไฝฟๅ…ƒ็ด ๅ…ทๅค‡ๅฏๆ‹–ๆ‹ฝ่กŒไธบ็š„่‡ชๅฎšไน‰้’ฉๅญ๏ผŒๆไพ›ๅฏ่‡ชๅฎšไน‰ๆˆ–็ฆ็”จ็š„ๆ‹–ๆ‹ฝ้ข„่งˆๆ•ˆๆžœใ€‚

<API name="useDraggable"> <APIOptions type="object"> <APIItem name="element" type="TElement"> ่ฆ่ฎพไธบๅฏๆ‹–ๆ‹ฝ็š„ๅ…ƒ็ด  </APIItem> <APIItem name="orientation" type="'horizontal' | 'vertical'" optional> ๆ‹–ๆ‹ฝๆ–นๅ‘ - **้ป˜่ฎคๅ€ผ:** `'vertical'` </APIItem> <APIItem name="type" type="string" optional> ๆ‹–ๆ‹ฝ้กน็ฑปๅž‹ - **้ป˜่ฎคๅ€ผ:** `'block'` </APIItem> <APIItem name="onDropHandler" type="function" optional> ๅ…ƒ็ด ๆ”พ็ฝฎๆ—ถ็š„ๅค„็†ๅ‡ฝๆ•ฐ </APIItem> </APIOptions> <APIReturns type="object"> <APIItem name="handleRef" type="(element: Element | React.ReactElement | React.RefObject<any> | null) => void"> ๆ‹–ๆ‹ฝๆบ่ฟžๆŽฅๅ‡ฝๆ•ฐ </APIItem> <APIItem name="isDragging" type="boolean"> ๅ…ƒ็ด ๆ˜ฏๅฆๆญฃๅœจ่ขซๆ‹–ๆ‹ฝ </APIItem> <APIItem name="previewRef" type="React.RefObject<HTMLDivElement>"> ๅฏๆ‹–ๆ‹ฝๅ…ƒ็ด ็š„ๅผ•็”จ </APIItem> </APIReturns> </API>

useDropNode

ไฝฟ็”จ react-dnd ็š„ useDrop ้’ฉๅญๅฎž็Žฐ่Š‚็‚นๆ”พ็ฝฎๅŠŸ่ƒฝ็š„่‡ชๅฎšไน‰้’ฉๅญใ€‚

<API name="useDropNode"> <APIOptions type="UseDropNodeOptions"> <APIItem name="nodeRef" type="any"> ่ขซๆ‹–ๆ‹ฝ่Š‚็‚น็š„ๅผ•็”จ </APIItem> <APIItem name="element" type="TElement"> ๆ”พ็ฝฎ็บฟไพ้™„็š„่Š‚็‚น </APIItem> <APIItem name="dropLine" type="string"> ๅฝ“ๅ‰ๆ”พ็ฝฎ็บฟ็š„ๅ€ผ </APIItem> <APIItem name="onChangeDropLine" type="function"> ๆ”พ็ฝฎ็บฟๅ˜ๅŒ–ๆ—ถ็š„ๅ›ž่ฐƒ </APIItem> <APIItem name="onDropHandler" type="object"> ๆ‹ฆๆˆชๆ”พ็ฝฎๅค„็†็š„ๅ›ž่ฐƒ - ่ฟ”ๅ›ž `true` ้˜ปๆญข้ป˜่ฎค่กŒไธบ - ่ฟ”ๅ›ž `false` ๆ‰ง่กŒ้ป˜่ฎค่กŒไธบ </APIItem> </APIOptions> </API>

useDropLine

่ฟ”ๅ›žๅ…ƒ็ด ็š„ๅฝ“ๅ‰ๆ”พ็ฝฎ็บฟ็Šถๆ€ใ€‚

<API name="useDropLine"> <APIOptions type="object"> <APIItem name="id" type="string" optional> ๆ˜พ็คบๆ”พ็ฝฎ็บฟ็š„ๅ…ƒ็ด ID - **้ป˜่ฎคๅ€ผ:** ๅฝ“ๅ‰ๅ…ƒ็ด ID </APIItem> <APIItem name="orientation" type="'horizontal' | 'vertical'" optional> ๆŒ‰ๆ–นๅ‘่ฟ‡ๆปคๆ”พ็ฝฎ็บฟ - **้ป˜่ฎคๅ€ผ:** `'vertical'` </APIItem> </APIOptions> <APIReturns type="object"> <APIItem name="dropLine" type="'top' | 'bottom' | 'left' | 'right' | ''"> ๅฝ“ๅ‰ๆ”พ็ฝฎ็บฟๆ–นๅ‘ </APIItem> </APIReturns> </API>
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

โ† Root | โ†‘ Up