Files
AFFiNE-Mirror/packages/frontend/component/package.json
doouding 99717196c5 refactor: rewrite blocksuite dnd (#9595)
### Changed

- Refactored BlockSuite drag-and-drop using @atlaskit/pragmatic-drag-and-drop/element/adapter.
- Updated block dragging to use the new drag-and-drop infrastructure.

### BlockSuite DND API

Access the BlockSuite drag-and-drop API via `std.dnd`. This is a lightweight wrapper around pragmatic-drag-and-drop, offering convenient generic types and more intuitive option names.

#### Drag payload structure
There's some constrain about drag payload. The whole drag payload looks like this:

```typescript
type DragPayload = {
  entity: {
    type: string
  },
  from: {
    at: 'blocksuite',
    docId: string
  }
}
```
- The `from` field is auto-generated—no need for manual handling.
- The `entity` field is customizable, but it must include a `type`.

All drag-and-drop methods accept a generic type for entity, ensuring more accurate payloads in event handlers.

```typescript
type BlockEntity = {
  type: 'blocks',
  blockIds: string[]
}

dnd.draggable<BlockEntity>({
  element: someElement,
  setDragData: () => {
    // the return type must satisfy the generic type
    // in this case, it's BlockEntity
    return {
      type: 'blocks',
      blockIds: []
    }
  }
});

dnd.monitor<BlockEntity>({
  // the arguments is same for other event handler
  onDrag({ source }) {
    // the type of this is BlockEntity
    source.data.entity
  }
})
```

#### Drop payload
When hover on droppable target. You can set drop payload as well. All drag-and-drop methods accept a second generic type for drop payload.

The drop payload is customizable. Additionally, the DND system will add an `edge` field to the final payload object, indicating the nearest edge of the drop target relative to the current drag position.

```typescript
type DropPayload = {
  blockId: string;
}

dnd.dropTarget<BlockEntity, DropPayload>({
  getData() {
    // the type should be DropPayload
    return {
      blockId: 'someId'
    }
  }
});

dnd.monitor<BlockEntity, DropPayload>({
  // drag over on drop target
  onDrag({ location }) {
    const target = location.current.dropTargets[0];

    // the type is DropPayload
    target.data;
    // retrieve the nearest edge of the drop target relative to the current drop position.
    target.data.edge;
  }
})
```
2025-01-16 12:36:58 +00:00

89 lines
2.7 KiB
JSON

{
"name": "@affine/component",
"private": true,
"main": "./src/index.ts",
"exports": {
".": "./src/index.ts",
"./theme": "./src/theme/index.ts",
"./ui/*": "./src/ui/*/index.ts",
"./*": "./src/components/*/index.tsx"
},
"scripts": {
"dev": "storybook dev -p 6006",
"build:storybook": "storybook build"
},
"peerDependencies": {
"@blocksuite/affine": "*",
"@swc/core": "^1.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"dependencies": {
"@affine/debug": "workspace:*",
"@affine/electron-api": "workspace:*",
"@affine/graphql": "workspace:*",
"@affine/i18n": "workspace:*",
"@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
"@blocksuite/icons": "2.2.2",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@radix-ui/react-avatar": "^1.1.2",
"@radix-ui/react-collapsible": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.3",
"@radix-ui/react-dropdown-menu": "^2.1.3",
"@radix-ui/react-popover": "^1.1.3",
"@radix-ui/react-progress": "^1.1.1",
"@radix-ui/react-radio-group": "^1.2.2",
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-slider": "^1.2.2",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-toast": "^1.2.3",
"@radix-ui/react-tooltip": "^1.1.5",
"@radix-ui/react-visually-hidden": "^1.1.1",
"@toeverything/theme": "^1.1.3",
"@vanilla-extract/dynamic": "^2.1.2",
"check-password-strength": "^2.0.10",
"clsx": "^2.1.1",
"dayjs": "^1.11.13",
"jotai": "^2.10.3",
"lit": "^3.2.1",
"lodash-es": "^4.17.21",
"lottie-react": "^2.4.0",
"lottie-web": "^5.12.2",
"nanoid": "^5.0.9",
"next-themes": "^0.4.4",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-paginate": "^8.2.0",
"react-router-dom": "^6.28.0",
"react-transition-state": "^2.2.0",
"sonner": "^1.7.1",
"swr": "^2.2.5",
"zod": "^3.24.1"
},
"devDependencies": {
"@blocksuite/affine": "workspace:*",
"@blocksuite/icons": "2.2.2",
"@chromatic-com/storybook": "^3.2.2",
"@storybook/addon-essentials": "^8.4.7",
"@storybook/addon-interactions": "^8.4.7",
"@storybook/addon-links": "^8.4.7",
"@storybook/addon-mdx-gfm": "^8.4.7",
"@storybook/react": "^8.4.7",
"@storybook/react-vite": "^8.4.7",
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.1.0",
"@types/react": "^19.0.1",
"@types/react-dom": "^19.0.2",
"@vanilla-extract/css": "^1.16.1",
"storybook": "^8.4.7",
"typescript": "^5.7.2",
"unplugin-swc": "^1.5.1",
"vite": "^6.0.3",
"vitest": "2.1.8"
},
"version": "0.19.0"
}