Commit Graph

79 Commits

Author SHA1 Message Date
fundon c43e1bcc4e refactor(editor): split openFileOrFiles into openSingleFileWith and openFilesWith (#12523)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
	- Improved file selection dialogs for attachments, imports, and uploads, allowing for more consistent and streamlined file picking across the app.

- **Bug Fixes**
	- Resolved inconsistencies when selecting single or multiple files, ensuring a smoother user experience during file import and upload.

- **Refactor**
	- Unified and simplified file selection logic throughout the app for better reliability and maintainability.
	- Standardized import functions to uniformly handle arrays of files, enhancing consistency in file processing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-28 03:06:33 +00:00
zzj3720 0f1a3c212d refactor(editor): add a layer of ui-logic to enhance type safety (#12511)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced modular UI logic layers for Kanban and Table views, enhancing maintainability and scalability.
  - Added new CSS-in-JS style modules for database blocks and table views, improving visual consistency.
  - Expanded telemetry event tracking for database views, properties, filters, and groups.
  - Added utility functions for lazy initialization and cached computed values.

- **Refactor**
  - Unified logic and state management across Kanban and Table views by replacing direct component dependencies with logic-centric architecture.
  - Updated components and widgets to use the new logic-based approach for state, selection, and event handling.
  - Replaced inline styles with CSS classes; updated class names to align with new component structure.
  - Centralized state access through UI logic instances, eliminating direct DOM queries and simplifying dependencies.
  - Consolidated Kanban and Table view presets effects for streamlined initialization.
  - Replaced Lit reactive state with Preact signals in multiple components for improved reactivity.
  - Split monolithic components into separate logic and UI classes for clearer separation of concerns.
  - Removed obsolete components and consolidated exports for cleaner API surface.

- **Bug Fixes**
  - Enhanced selection and interaction reliability in database cells and views.
  - Fixed scrolling issues on mobile table views for improved compatibility.

- **Chores**
  - Updated end-to-end test selectors to reflect new component names and structure.
  - Removed deprecated utilities and cleaned up unused imports.

- **Documentation**
  - Improved type definitions and public API exports for better developer experience.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-27 09:36:44 +00:00
fundon d0539fde22 fix(editor): unify file size formatting method (#12444)
Closes: [BS-3524](https://linear.app/affine-design/issue/BS-3524/统一文件大小单位,与-af-一致)

![Screenshot 2025-05-22 at 15.09.41.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/8ypiIKZXudF5a0tIgIzf/ddb6fa38-243f-4e65-b572-d476e3771d74.png)

![Screenshot 2025-05-22 at 15.09.48.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/8ypiIKZXudF5a0tIgIzf/5d182332-4d0a-419a-b206-df58552fe740.png)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Refactor**
  - Updated file size formatting throughout the app to use a new, consistent utility for displaying file sizes.
  - Improved clarity and uniformity of file size information in attachments, images, and related notifications.
  - Enhanced type support to explicitly allow null values for file size descriptions.
- **Bug Fixes**
  - Adjusted file size display in tests to match updated formatting standards.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-23 06:33:31 +00:00
fundon fd838d4e2d fix(editor): should add HTTP protocol into link automatically (#11934)
Closes: [BS-3291](https://linear.app/affine-design/issue/BS-3291/工具栏展开时报错,链接无法点击打开)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - URLs entered without a protocol (e.g., "github.com/...") are now automatically normalized to use "https://", ensuring links are secure and consistently formatted.

- **Bug Fixes**
  - Improved handling and validation of links to prevent issues with missing or invalid protocols in bookmarks and inline links.
  - Simplified URL validation logic by leveraging native URL parsing, removing complex regex and email-specific checks.
  - Streamlined toolbar link actions to operate only on valid normalized URLs.
  - Refined URL detection in markdown preprocessing to exclude lines containing spaces from being treated as URLs.

- **Tests**
  - Added tests to verify that links without a protocol are correctly normalized and displayed across different views.
  - Updated URL validation tests to better reflect valid and invalid URL formats, including IP addresses and domain variants.

- **Style**
  - Updated snapshots to reflect the use of "https://" in links.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-19 17:05:06 +00:00
Saul-Mirone 95b9e4b3d0 refactor(editor): rename model.doc to store (#12172) 2025-05-07 09:17:01 +00:00
Saul-Mirone d859c4252b refactor(editor): move history from doc to store (#12131)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Undo/redo history management is now centralized in the workspace, providing more consistent and robust undo/redo behavior.
  - History update events are emitted at the workspace level, enabling better tracking of changes.

- **Bug Fixes**
  - Improved reliability of undo/redo actions by shifting history management from documents to the workspace.

- **Documentation**
  - Updated and clarified documentation for history-related APIs, including improved examples and clearer descriptions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-05 09:24:09 +00:00
Saul-Mirone 45b6cbe8d7 refactor(editor): cleanup dead code (#11893) 2025-04-22 15:51:23 +00:00
fundon c0ff567a2a fix(editor): get block props (#11807)
Closes: [BS-3184](https://linear.app/affine-design/issue/BS-3184/duplicate-图片,一直在loading)
2025-04-18 10:59:31 +00:00
fundon eb0bcd9b99 fix(editor): improve menu content UX on toolbar (#11491)
* Added scrollbar style

![Screenshot 2025-04-07 at 11.50.19.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/8ypiIKZXudF5a0tIgIzf/c2a44dcc-7f24-44d5-a855-e2c1671e85f9.png)

* Used `padding` instead of `offset`
2025-04-07 06:30:07 +00:00
Saul-Mirone 205cd7a86d refactor(editor): rename block-std to std (#11250)
Closes: BS-2946
2025-03-28 07:20:34 +00:00
fundon 2c4278058b feat(editor): add highlighter (#10573)
Closes: [BS-2909](https://linear.app/affine-design/issue/BS-2909/新增highlighter)

### What's Changed!

Currently the highlighter tool is very similar to brush, but for the future, it's a standalone module.

* Added `Highlighter` element model
* Added `Highlighter` tool
* Added `Highlighter` entry to the global toolbar
2025-03-27 08:53:26 +00:00
Saul-Mirone 0a8d8e0a6b feat: seperate createDoc and createStore (#11182) 2025-03-26 11:03:47 +00:00
fundon 583bbf3463 fix(editor): improve affine-link toolbar (#11159)
Closes: [BS-2884](https://linear.app/affine-design/issue/BS-2884/[ui]-hover-邮箱的-toolbar)
2025-03-25 07:58:41 +00:00
L-Sun a2e3d318ba refactor(editor): adjust ui of surface-ref inner toolbar (#11129)
Close [BS-2803](https://linear.app/affine-design/issue/BS-2803/inserted-frame-ui%E8%B0%83%E6%95%B4)
Close [BS-2815](https://linear.app/affine-design/issue/BS-2815/inserted-group-ui调整)

### What Changes
- Add an inner toolbar for hovered `surface-ref-block`
- Simplify viewport related codes of `surface-ref-block`
- Expose popover floating options from `affine-menu-button`

https://github.com/user-attachments/assets/916b0a22-6271-4a6f-b338-6630e0426967
2025-03-25 03:48:12 +00:00
Saul-Mirone 66ea3038af refactor(editor): align rich text util apis (#11039) 2025-03-20 10:40:11 +00:00
L-Sun da63d51b7e refactor(editor): group and expose parameters of createButtonPopper (#10999) 2025-03-20 08:37:59 +00:00
Saul-Mirone 92d76ba571 refactor(editor): merge inline to std (#11025) 2025-03-20 05:46:56 +00:00
fundon 1acc7e5a9e refactor(editor): edgeless text toolbar config extension (#10811) 2025-03-20 02:08:15 +00:00
fundon 7f34667b78 refactor(editor): edgeless connector toolbar config extension (#10798) 2025-03-19 14:50:55 +00:00
fundon e320552594 refactor(editor): edgeless note toolbar config extension (#10719) 2025-03-19 12:34:18 +00:00
Saul-Mirone 3de7d85eea feat(editor): improve api for store, and add docs (#10941) 2025-03-17 16:30:59 +00:00
Saul-Mirone 26285f7dcb feat(editor): unify block props api (#10888)
Closes: [BS-2707](https://linear.app/affine-design/issue/BS-2707/统一使用props获取和更新block-prop)
2025-03-16 05:48:34 +00:00
L-Sun 3b4453d2b8 chore(editor): update default width of page block (#10873)
Close [BS-2498](https://linear.app/affine-design/issue/BS-2498/page-block首次切换时默认宽度为800px)
2025-03-14 12:59:17 +00:00
yoyoyohamapi aa15b106d9 feat(editor): content block getter command (#10720)
### TL;DR
Added new commands to retrieve the first and last content blocks in a document.

### What changed?
- Created `getFirstContentBlockCommand` to find the first content block in a document
- Created `getLastContentBlockCommand` to find the last content block in a document
- Added `getFirstNoteBlock` utility function to find the first note block in a document
2025-03-14 02:35:20 +00:00
Mirone cd63e0ed8b feat(editor): replace slot with rxjs subject (#10768) 2025-03-12 11:29:24 +09:00
L-Sun 62d8c0c7cb refactor(editor): adjust folder structure for slash menu extension (#10588)
Close [BS-2743](https://linear.app/affine-design/issue/BS-2743/slash-menu插件化:调整文件夹结构)

This PR move slash menu from `affine-root-block` to `widget-affine-slash-menu`, and make it as a `WidgetViewExtension`
2025-03-06 16:12:06 +00:00
Saul-Mirone 84e2dda3f8 refactor(editor): separate lit and slot in global (#10666) 2025-03-06 10:24:59 +00:00
fundon ec9bd1f383 feat(editor): add toolbar registry extension (#9572)
### What's Changed!

#### Added
Manage various types of toolbars uniformly in one place.

* `affine-toolbar-widget`
* `ToolbarRegistryExtension`

The toolbar currently supports and handles several scenarios:

1.  Select blocks: `BlockSelection`
2. Select text: `TextSelection` or `NativeSelection`
3. Hover a link: `affine-link` and `affine-reference`

#### Removed
Remove redundant toolbar implementations.

* `attachment` toolbar
* `bookmark` toolbar
* `embed` toolbar
* `formatting` toolbar
* `affine-link` toolbar
* `affine-reference` toolbar

### How to migrate?

Here is an example that can help us migrate some unrefactored toolbars:

Check out the more detailed types of [`ToolbarModuleConfig`](https://github.com/toeverything/AFFiNE/blob/c178debf2d49c40b753e1bcaa6f07270bdde7401/blocksuite/affine/shared/src/services/toolbar-service/config.ts).

1.  Add toolbar configuration file to a block type, such as bookmark block: [`config.ts`](https://github.com/toeverything/AFFiNE/blob/c178debf2d49c40b753e1bcaa6f07270bdde7401/blocksuite/affine/block-bookmark/src/configs/toolbar.ts)

```ts
export const builtinToolbarConfig = {
  actions: [
    {
      id: 'a.preview',
      content(ctx) {
        const model = ctx.getCurrentModelBy(BlockSelection, BookmarkBlockModel);
        if (!model) return null;

        const { url } = model;

        return html`<affine-link-preview .url=${url}></affine-link-preview>`;
      },
    },
    {
      id: 'b.conversions',
      actions: [
        {
          id: 'inline',
          label: 'Inline view',
          run(ctx) {
          },
        },
        {
          id: 'card',
          label: 'Card view',
          disabled: true,
        },
        {
          id: 'embed',
          label: 'Embed view',
          disabled(ctx) {
          },
          run(ctx) {
          },
        },
      ],
      content(ctx) {
      },
    } satisfies ToolbarActionGroup<ToolbarAction>,
    {
      id: 'c.style',
      actions: [
        {
          id: 'horizontal',
          label: 'Large horizontal style',
        },
        {
          id: 'list',
          label: 'Small horizontal style',
        },
      ],
      content(ctx) {
      },
    } satisfies ToolbarActionGroup<ToolbarAction>,
    {
      id: 'd.caption',
      tooltip: 'Caption',
      icon: CaptionIcon(),
      run(ctx) {
      },
    },
    {
      placement: ActionPlacement.More,
      id: 'a.clipboard',
      actions: [
        {
          id: 'copy',
          label: 'Copy',
          icon: CopyIcon(),
          run(ctx) {
          },
        },
        {
          id: 'duplicate',
          label: 'Duplicate',
          icon: DuplicateIcon(),
          run(ctx) {
          },
        },
      ],
    },
    {
      placement: ActionPlacement.More,
      id: 'b.refresh',
      label: 'Reload',
      icon: ResetIcon(),
      run(ctx) {
      },
    },
    {
      placement: ActionPlacement.More,
      id: 'c.delete',
      label: 'Delete',
      icon: DeleteIcon(),
      variant: 'destructive',
      run(ctx) {
      },
    },
  ],
} as const satisfies ToolbarModuleConfig;
```

2. Add configuration extension to a block spec: [bookmark's spec](https://github.com/toeverything/AFFiNE/blob/c178debf2d49c40b753e1bcaa6f07270bdde7401/blocksuite/affine/block-bookmark/src/bookmark-spec.ts)

```ts
const flavour = BookmarkBlockSchema.model.flavour;

export const BookmarkBlockSpec: ExtensionType[] = [
  ...,
  ToolbarModuleExtension({
    id: BlockFlavourIdentifier(flavour),
    config: builtinToolbarConfig,
  }),
].flat();
```

3. If the bock type already has a toolbar configuration built in, we can customize it in the following ways:

Check out the [editor's config](https://github.com/toeverything/AFFiNE/blob/c178debf2d49c40b753e1bcaa6f07270bdde7401/packages/frontend/core/src/blocksuite/extensions/editor-config/index.ts#L51C4-L54C8) file.

```ts
// Defines a toolbar configuration for the bookmark block type
const customBookmarkToolbarConfig = {
  actions: [
    ...
  ]
} as const satisfies ToolbarModuleConfig;

// Adds it into the editor's config
 ToolbarModuleExtension({
    id: BlockFlavourIdentifier('custom:affine:bookmark'),
    config: customBookmarkToolbarConfig,
 }),
```

4. If we want to extend the global:

```ts
// Defines a toolbar configuration
const customWildcardToolbarConfig = {
  actions: [
    ...
  ]
} as const satisfies ToolbarModuleConfig;

// Adds it into the editor's config
 ToolbarModuleExtension({
    id: BlockFlavourIdentifier('custom:affine:*'),
    config: customWildcardToolbarConfig,
 }),
```

Currently, only most toolbars in page mode have been refactored. Next is edgeless mode.
2025-03-06 06:46:03 +00:00
Saul-Mirone 2b30d756e2 refactor(editor): replace debounce and throttle with lodash (#10639) 2025-03-06 04:46:52 +00:00
Saul-Mirone 7e39893aac refactor(editor): remove assert functions (#10629) 2025-03-05 10:20:02 +00:00
Saul-Mirone b8ecfbdae6 refactor(editor): remove assertExists (#10615) 2025-03-05 00:13:08 +00:00
Saul-Mirone 66d9d576e0 refactor(editor): add gfx entry in bs global package (#10612) 2025-03-04 12:46:50 +00:00
Saul-Mirone 5ad3d3c94a refactor(editor): move figma squircle to shared (#10610) 2025-03-04 10:26:58 +00:00
Saul-Mirone 4c3c953a36 chore(editor): merge clamp functions (#10577)
Closes: [BS-2625](https://linear.app/affine-design/issue/BS-2625/合并clamp函数)
2025-03-03 10:33:38 +00:00
doodlewind 12acf7e4a0 fix(editor): range IndexSizeError on firefox (#10519)
This is a Firefox compat issue, I've manually confirmed this implementation works in latest Firefox build.
2025-02-28 11:50:56 +00:00
Saul-Mirone 4c736bc190 feat(editor): type safe draft model and transformer (#10486) 2025-02-27 09:19:49 +00:00
Saul-Mirone 9435118ef1 refactor(editor): optimize ai code structure (#10381)
Let me analyze this diff and provide a clear description of the changes.

This PR introduces several significant changes focused on AI integration and code organization in the AFFiNE codebase:

1. **Enhanced SpecBuilder Functionality** (`blocksuite/affine/shared/src/utils/spec/spec-builder.ts`):
   - Added method chaining by returning `this` from `extend`, `omit`, and `replace` methods
   - Added new utility methods:
     - `hasAll(target: ExtensionType[])`: Checks if all specified extensions exist
     - `hasOneOf(target: ExtensionType[])`: Checks if at least one specified extension exists

2. **AI Extensions Modularization**:
   - Split the large AI-related code into separate modular files under `packages/frontend/core/src/blocksuite/ai/extensions/`:
     - `ai-code.ts`: Code block AI integration
     - `ai-edgeless-root.ts`: Edgeless mode AI features
     - `ai-image.ts`: Image block AI capabilities
     - `ai-page-root.ts`: Page root AI integration
     - `ai-paragraph.ts`: Paragraph block AI features
     - `enable-ai.ts`: Central AI extension enablement logic

3. **Widget Improvements**:
   - Enhanced `AffineAIPanelWidget` and `EdgelessCopilotWidget` with proper widget extensions
   - Moved widget-specific extensions into their respective files
   - Added proper type definitions and component registrations

4. **Code Organization**:
   - Simplified exports in `index.ts`
   - Better separation of concerns between different AI-related components
   - More modular approach to AI feature integration

5. **AI Integration Architecture**:
   - Introduced a new `enableAIExtension` function that handles:
     - Replacing standard blocks with AI-enhanced versions
     - Conditional enabling of AI features based on the current spec configuration
     - Extension of AI chat capabilities

The changes primarily focus on improving code organization, maintainability, and the architecture of AI feature integration in the AFFiNE editor. The modularization will make it easier to maintain and extend AI capabilities across different block types and editor modes.
2025-02-24 04:30:08 +00:00
Saul-Mirone 2cf9a8f286 refactor: reorganize specs and adapter extensions (#10359)
### TL;DR
Refactored `SpecProvider` singleton access pattern and reorganized adapter/extension code structure.

### What changed?
- Changed `SpecProvider.getInstance()` to `SpecProvider._` for cleaner singleton access
- Moved adapter/extension code from `_common` directory to dedicated `adapters` and `extensions` folders
- Consolidated adapter extensions into a single file
- Removed unused dependencies from package.json
- Deleted unnecessary schema files
- Extracted `MobileSpecsPatches` class into the mobile patching code
- Updated all references to use the new `SpecProvider._` accessor

### How to test?
- Verify all specs are properly registered and accessible via `SpecProvider._`
- Test adapter functionality for HTML, Markdown, Notion HTML and plain text
- Check mobile-specific features and patches work correctly
- Ensure preview functionality works in both page and edgeless modes

### Why make this change?
- Improves code organization by properly separating adapters and extensions
- Simplifies singleton access pattern
- Removes unnecessary dependencies and files
- Makes the codebase more maintainable by consolidating related functionality
2025-02-21 14:25:35 +00:00
Saul-Mirone 22e4bd8c20 refactor: move image proxy middleware and adapter extensions (#10345)
### TL;DR
Moved image proxy middleware and adapter extensions to their respective packages and introduced a new spec provider for adapter registration.

### What changed?
- Relocated `defaultImageProxyMiddleware` from blocks to `@blocksuite/affine-block-image`
- Moved `PresentTool` from fragment-frame-panel to block-frame
- Created new adapter extension specs for HTML, Markdown, and Notion HTML
- Introduced a spec provider pattern for adapter registration
- Removed direct transformer references from RootService
- Updated imports across affected files to use new locations

### How to test?
1. Verify image proxy functionality works in exports and imports
2. Test HTML, Markdown, and Notion HTML adapters still function correctly
3. Confirm presentation mode works with the relocated PresentTool
4. Check that all file import/export operations continue to work as expected

### Why make this change?
This reorganization improves code modularity by placing features in their logical packages and introduces a more maintainable pattern for adapter registration. The spec provider pattern makes it easier to manage and extend adapter functionality while reducing coupling between components.
2025-02-21 09:01:57 +00:00
fundon adc003862b fix(editor): image size and xywh when converting attachment to image (#10200)
In Edgeless, the image size should be read when converting attachment to image:

* fix `size`
* fix `xywh`
2025-02-20 05:16:21 +00:00
Saul-Mirone 2f04e3180c refactor: move utils and cleanup test helpers (#10261) 2025-02-18 14:03:51 +00:00
Alexey Lysenko 769547c2d5 fix(editor): support more divider markdown shortcut (#10139) 2025-02-14 10:13:40 +08:00
L-Sun 9a17422d36 fix(editor): wrong position of remote selection and at menu in edgeless (#10137)
Close [BS-2552](https://linear.app/affine-design/issue/BS-2552/menu-loading-时滚动,定位错误), [BS-2490](https://linear.app/affine-design/issue/BS-2490/note-block-的menu的输入阴影错位), [BS-2300](https://linear.app/affine-design/issue/BS-2300/at-menu的输入阴影在暗黑模式看不见)

### What  Changes
- fix the position of remote selection mask and @ menu input mask in edgeless
- fix the position of @ menu is no updated during edgeless viewport change
- update @ menu mask color in dark mode

### Before
https://github.com/user-attachments/assets/f44f618e-a791-497a-9f53-74824fe48dea

### After
https://github.com/user-attachments/assets/5d87b999-deae-4435-9b8b-4cdf55393395
2025-02-13 01:56:01 +00:00
Saul-Mirone 39eb8625d6 refactor(editor): remove block models global type (#10086) 2025-02-11 11:00:57 +00:00
Saul-Mirone 652865c7cf refactor(editor): remove global types in model (#10082)
Closes: [BS-2249](https://linear.app/affine-design/issue/BS-2249/remove-global-types-in-model)

```ts
// before
matchFlavours(model, ['affine:page']);
// after
matchFlavours(model, [PageBlockModel]);
```
2025-02-11 08:18:57 +00:00
zzj3720 c78d6b81c6 feat(editor): table block supports drag-and-drop sorting (#10065)
close: BS-2477
2025-02-10 14:14:53 +00:00
L-Sun 459972fe6c fix(editor): add missing zod schema for edgeless frame (#10024)
Related to https://github.com/toeverything/AFFiNE/pull/9970#discussion_r1944971309

### What changes:
- Add missing zod shcema for edgeless basic props
- Change `applyLastProps` to generic function for better return type inference of
- Fix: add `ZodIntersection` case to `makeDeepOptional`
2025-02-07 12:49:59 +00:00
zzj3720 5a5779c05a feat(editor): simple table block (#9740)
close: BS-2122, BS-2125, BS-2124, BS-2420, PD-2073, BS-2126, BS-2469, BS-2470, BS-2478, BS-2471
2025-01-24 10:07:57 +00:00
doodlewind 872a578bf7 refactor(editor): move zod schema with model for non surface blocks (#9876) 2025-01-23 10:57:49 +00:00
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