1. **Table UI Enhancements - Test IDs Added**
- Added `data-testid` attributes to several table components for better testability:
- `add-column-button` for the column addition button
- `add-row-button` for the row addition button
- `drag-column-handle` for column drag handles
- `drag-row-handle` for row drag handles
2. **New Test Infrastructure**
- Added new testing utilities in `tests/kit/src/bs/`:
- `misc.ts`: Added `waitNextFrame` utility function for handling animation frame timing in tests
- `table.ts`: Added comprehensive table testing utilities including:
- `createTable`: Creates a new table with initial cells
- `getCellText`: Retrieves text from a specific table cell
- `inputToCell`: Inputs text into a specific table cell
- `clickDeleteButtonInTableMenu`: Handles table deletion operations
3. **New Collaboration Test**
- Added a new test file `tests/affine-local/e2e/blocksuite/table/collab.spec.ts` that tests table collaboration features:
- Tests synchronization between two pages (A and B)
- Verifies table operations sync correctly:
- Adding columns and rows
- Inputting cell content
- Deleting columns and rows
- Validates cell content consistency across both pages
- Tests the complete table manipulation workflow in a collaborative setting
4. **Package Configuration Update**
- Modified `tests/kit/package.json` to expose new test utilities:
- Added new export mapping: `"./bs/*": "./src/bs/*.ts"` to make the new table testing utilities accessible
This PR primarily focuses on improving table testing infrastructure and adding comprehensive collaboration tests for the table functionality, while also enhancing component testability through data-test-ids.
### TL;DR
Moved editor components from BlockSuite presets to AFFiNE core and updated imports accordingly.
### What changed?
- Relocated `EdgelessEditor` and `PageEditor` components from BlockSuite presets to AFFiNE core
- Removed basic editor examples from playground
- Updated import paths across the codebase to reference new component locations
- Added editor effects registration in AFFiNE core
- Removed editor exports from BlockSuite presets
### How to test?
1. Launch the application
2. Verify both page and edgeless editors load correctly
3. Confirm editor functionality remains intact including:
- Document editing
- Mode switching
- Editor toolbars and controls
- Multiple editor instances
### Why make this change?
This change better aligns with AFFiNE's architecture by moving editor components closer to where they are used. It reduces coupling with BlockSuite presets and gives AFFiNE more direct control over editor customization and implementation.
Close [BS-2458](https://linear.app/affine-design/issue/BS-2458/toc-dnd重构)
### What Changes
- Refactor toc note card dnd with `std.dnd`
- Extract note display mode change to command `changeNoteDisplayMode`
- It will reorder notes when the display mode changed from `EdgelessOnly` to page mode visible (a.k.a `DocOnly` or `Both`)
### What Changes
1. Used `@preact/signal` and `@lit/context` to simplify repetitive passing of properties of TOC components,
2. Fixed TOC invalid when editor changed, such as click new page button.
### 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;
}
})
```
Close [BS-2315](https://linear.app/affine-design/issue/BS-2315/page-block-header)
### What Changes
- Add header toolbar to page block (the first note in canvas)
- Add e2e tests
- Add some edgeless e2e test utils. **The package `@blocksuite/affine` was added to `"@affine-test/kit"`**