### Problem
●In edgeless mode, when using Shift + click to perform range selection
inside an editing `note-edgeless-block` (click at the starting point,
then hold Shift and click at the end point), the block will unexpectedly
lose its editing and selection state. As a result, subsequent operations
on the selection - such as deleting and moving - no longer work.
●The following video demonstrates this issue:
https://github.com/user-attachments/assets/82c68683-e002-4a58-b011-fe59f7fc9f02
### Solution
●The reason is that this "Shift + click" behavior is being handled by
the default multi-selection logic, which toggles selection mode and
exits the editing state. So I added an `else-if` branch to match this
case.
### After
●The video below shows the behavior after this fix.
https://github.com/user-attachments/assets/18d61108-2089-4def-b2dc-ae13fc5ac333
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved selection behavior during note editing in multi-select mode
to provide more intuitive interaction when using range selection during
active editing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Problem
●In edgeless mode, when the `note-edgeless-block` is scaled below 100%,
its outer dimension becomes larger than its content region. This extra
invisible region will block some user interactions such as clicks and
hovers on editing elements underneath.
<img width="1060" height="541" alt="note-elem-block-click"
src="https://github.com/user-attachments/assets/860d7a4f-d159-437b-bbe8-4560e2463e3d"
/>
●The following video demonstrates this issue:
https://github.com/user-attachments/assets/3b719b25-0d7e-496b-9507-6aa65ed0a797
### Solution
●The root cause is that `transform: scale(...)` CSS property (which
implements the scale) is currently applyed to its **inner root element**
instead of itself, and the solution is to move this CSS property to the
proper place.
### After
●The video below shows the behavior after this fix.
https://github.com/user-attachments/assets/e2dbd75d-c2ea-460d-90a1-5cc13e12d5b8
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Centralized CSS scaling for graphics and edgeless note blocks into
dedicated public methods; rendering now uses these methods instead of
inline transform calculations.
* **Tests**
* Updated end-to-end checks to read scale directly from the edgeless
note element and use a more flexible transform-matching pattern.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Problem
●In edgeless mode, when starting to edit, `note-block` exhibits two
types of invalid caret behavior:
(1)**Title Region Misalignment**: Clicking on the title region
incorrectly generates the caret in the first line of the note content,
rather than in the title itself.
(2)**Vanishing Caret at Line End**: When clicking in the empty space
beyond the end of a text section, the caret appears momentarily at the
line's end but disappears immediately.
●The following video demonstrates these issues:
https://github.com/user-attachments/assets/db9c2c50-709f-4d32-912c-0f01841d2024
### Solution
●**Title Click Interception**: Added a check to determine if the click
coordinates fall in the title region. If so, the caret positioning is
now handled by a dedicated logic path. Otherwise, it falls back to the
existing note-content logic as before.
●**Range Normalization**: When the generated `range.startContainer` is
not a `TextNode`, try to find a most appropriate `TextNode` and update
the `range` accordingly.
### After
●The video below shows the behavior after this fix.
https://github.com/user-attachments/assets/b2f70b64-1fc6-4049-8379-8bcf3a488a05
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Clicking a page block title no longer creates unwanted paragraphs and
reliably focuses the title.
* Paragraph creation now occurs only when needed and focus is applied
only after successful creation.
* Click coordinates are clamped to container bounds to prevent misplaced
cursors or focus.
* **Improvements**
* Caret normalization: clicks place the caret at the last meaningful
text position for consistent single-cursor behavior.
* **Tests**
* Added end-to-end coverage for caret placement and focus transitions.
* New ratio-based click/double-click test utilities and a helper for
double-clicking note bodies.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Changed
- Note scale issue
- Overlay should call refresh when `clear` is called
- Optimize edgeless-selected-rect to avoid unecessary rerendering
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
- **New Features**
- Edgeless note blocks now respect both minimum and maximum size limits when resizing.
- **Improvements**
- Enhanced performance and responsiveness of resize and rotate handles in selection overlays by caching allowed handles and optimizing cursor management.
- Cursor styles for resize and rotate handles are now set more reliably and efficiently through declarative styling.
- **Bug Fixes**
- Ensured overlay clearing now properly refreshes the renderer for more consistent visual updates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes [BS-3528](https://linear.app/affine-design/issue/BS-3528)
Fixes [BS-3331](https://linear.app/affine-design/issue/BS-3331/frame-移动逻辑很奇怪)
### Changed
- Remove `onSelected` method from gfx view, use `handleSelection` provided by `GfxViewInteraction` instead.
- Add `selectable` to allow model to filter out itself from selection.
- Frame can be selected by body only if it's locked or its background is not transparent.
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
- **New Features**
- Enhanced selection behavior for frames, edgeless text, notes, and mind map elements with refined control based on lock state and background transparency.
- Introduced group-aware selection logic promoting selection of appropriate group ancestors.
- Added support for element selection events in interactivity extensions.
- **Bug Fixes**
- Resolved frame selection issues by enabling selection via title clicks and restricting body selection to locked frames or those with non-transparent backgrounds.
- **Documentation**
- Added clarifying comments for group retrieval methods.
- **Tests**
- Updated and added end-to-end tests for frame and lock selection reflecting new selection conditions.
- **Refactor**
- Unified and simplified selection handling by moving logic from component methods to interaction handlers and removing deprecated selection methods.
- Streamlined selection candidate processing with extension-driven target suggestion.
- Removed legacy group element retrieval and selection helper methods to simplify interaction logic.
- **Style**
- Renamed types and improved type signatures for selection context and interaction configurations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Changed
This pr split the old `edgeless-selected-rect` into four focused modules:
- `edgeless-selected-rect`: Provide an entry point for user operation on view layer only, no further logic here.
- `GfxViewInteractionExtension`: Allow you to plug in custom resize/rotate behaviors for block or canvas element. If you don’t register an extension, it falls back to the default behaviours.
- `InteractivityManager`: Provide the API that accepts resize/rotate requests, invokes any custom behaviors you’ve registered, tracks the lifecycle and intermediate state, then hands off to the math engine.
- `ResizeController`: A pure math engine that listens for pointer moves and pointer ups and calculates new sizes, positions, and angles. It doesn’t call any business APIs.
### Customizing an element’s resize/rotate behavior
Call `GfxViewInteractionExtension` with the element’s flavour or type plus a config object. In the config you can define:
- `resizeConstraint` (min/max width & height, lock ratio)
- `handleResize(context)` method that returns an object containing `beforeResize`、`onResizeStart`、`onResizeMove`、`onResizeEnd`
- `handleRotate(context)` method that returns an object containing `beforeRotate`、`onRotateStart`、`onRotateMove`、`onRotateEnd`
```typescript
import { GfxViewInteractionExtension } from '@blocksuite/std/gfx';
GfxViewInteractionExtension(
flavourOrElementType,
{
resizeConstraint: {
minWidth,
maxWidth,
lockRatio,
minHeight,
maxHeight
},
handleResize(context) {
return {
beforeResize(context) {},
onResizeStart(context) {},
onResizeMove(context) {},
onResizeEnd(context) {}
};
},
handleRotate(context) {
return {
beforeRotate(context) {},
onRotateStart(context) {},
onRotateMove(context) {},
onRotateEnd(context) {}
};
}
}
);
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
- **New Features**
- Added interaction extensions for edgeless variants of attachment, bookmark, edgeless text, embedded docs, images, notes, frames, AI chat blocks, and various embed blocks (Figma, GitHub, HTML, iframe, Loom, YouTube).
- Introduced interaction extensions for graphical elements including connectors, groups, mind maps, shapes, and text, supporting constrained resizing and rotation disabling where applicable.
- Implemented a unified interaction extension framework enabling configurable resize and rotate lifecycle handlers.
- Enhanced autocomplete overlay behavior based on selection context.
- **Refactor**
- Removed legacy resize manager and element-specific resize/rotate logic, replacing with a centralized, extensible interaction system.
- Simplified resize handle rendering to a data-driven approach with improved cursor management.
- Replaced complex cursor rotation calculations with fixed-angle mappings for resize handles.
- Streamlined selection rectangle component to use interactivity services for resize and rotate handling.
- **Bug Fixes**
- Fixed connector update triggers to reduce unnecessary updates.
- Improved resize constraints enforcement and interaction state tracking.
- **Tests**
- Refined end-to-end tests to use higher-level resize utilities and added finer-grained assertions on element dimensions.
- Enhanced mouse movement granularity in drag tests for better simulation fidelity.
- **Chores**
- Added new workspace dependencies and project references for the interaction framework modules.
- Extended public API exports to include new interaction types and extensions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
- **Refactor**
- Unified internal data access by replacing all references from `doc` to `store` across all components, blocks, widgets, and utilities. This affects how readonly state, block operations, and service retrieval are handled throughout the application.
- **Tests**
- Updated all test utilities and test cases to use `store` instead of `doc` for document-related operations.
- **Chores**
- Updated context providers and property names to reflect the change from `doc` to `store` for improved consistency and maintainability.
No user-facing features or behaviors have changed.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Close [BS-3066](https://linear.app/affine-design/issue/BS-3066/优化长note的展示和折叠)
- Enhanced the visibility behavior of hidden content in edgeless notes by:
- Showing hidden content when a note is being edited, even when it's outside the viewport
- Improving hover behavior with a delay when leaving from the bottom of the note
- Adding proper cleanup of hover timeouts when the component is disconnected
- Optimizing the viewport element to keep editing blocks or elements visible
## Testing
- Added new E2E test cases covering:
- Hover behavior on selected notes
- Content visibility during editing
- Viewport scrolling behavior
- Edge cases for content visibility
## Impact
This change improves the user experience when working with collapsed notes in edgeless mode by making the content more accessible and preventing accidental content hiding during editing.
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
- **Bug Fixes**
- Improved visibility of hidden content in edgeless notes when hovering near the bottom edge or editing the note, especially after resizing or clipping.
- **New Features**
- Enhanced hover behavior with delayed clearing based on mouse position to improve user experience.
- **Tests**
- Added new tests verifying hidden content visibility in edgeless notes during hover and editing, simulating diverse user interactions.
- **Chores**
- Added utilities to get and set viewport center for improved test control.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Changed
- Rewrite box selection in `default-tool`, the view can decide whether to be selected in box selection by return a boolean value in `onBoxSelected` method
- Cleanup unnecessary states in `default-tool` and some naming problem