Files
AFFiNE-Mirror/blocksuite/affine/widgets/edgeless-selected-rect/src/resize-handles.ts
T
doouding d49ecfbecc fix: avoid unnecessary rerendering of selected-rect (#12583)
### 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 -->
2025-05-28 03:53:51 +00:00

95 lines
2.6 KiB
TypeScript

import type { ResizeHandle } from '@blocksuite/std/gfx';
import { html, nothing } from 'lit';
import { repeat } from 'lit/directives/repeat.js';
import { styleMap } from 'lit/directives/style-map.js';
export enum HandleDirection {
Bottom = 'bottom',
BottomLeft = 'bottom-left',
BottomRight = 'bottom-right',
Left = 'left',
Right = 'right',
Top = 'top',
TopLeft = 'top-left',
TopRight = 'top-right',
}
function ResizeHandleRenderer(
handle: ResizeHandle,
rotatable: boolean,
onPointerDown?: (e: PointerEvent, direction: ResizeHandle) => void,
getCursor?: (options: {
type: 'resize' | 'rotate';
handle: ResizeHandle;
}) => string
) {
const handlerPointerDown = (e: PointerEvent) => {
e.stopPropagation();
onPointerDown && onPointerDown(e, handle);
};
const rotationTpl =
handle.length > 6 && rotatable
? html`<div
class="rotate"
style=${styleMap({
cursor: getCursor
? getCursor({
type: 'rotate',
handle,
})
: 'default',
})}
></div>`
: nothing;
return html`<div
class="handle"
aria-label=${handle}
@pointerdown=${handlerPointerDown}
>
${rotationTpl}
<div
class="resize transparent-handle"
style=${styleMap({
cursor: getCursor
? getCursor({
type: 'resize',
handle,
})
: 'default',
})}
></div>
</div>`;
}
/**
* Indicate how selected elements can be resized.
*
* - edge: The selected elements can only be resized dragging edge, usually when note element is selected
* - all: The selected elements can be resize both dragging edge or corner, usually when all elements are `shape`
* - none: The selected elements can't be resized, usually when all elements are `connector`
* - corner: The selected elements can only be resize dragging corner, this is by default mode
* - edgeAndCorner: The selected elements can be resize both dragging left right edge or corner, usually when all elements are 'text'
*/
export type ResizeMode = 'edge' | 'all' | 'none' | 'corner' | 'edgeAndCorner';
export function RenderResizeHandles(
resizeHandles: ResizeHandle[],
rotatable: boolean,
onPointerDown: (e: PointerEvent, direction: ResizeHandle) => void,
getCursor?: (options: {
type: 'resize' | 'rotate';
handle: ResizeHandle;
}) => string
) {
return html`
${repeat(
resizeHandles,
handle => handle,
handle =>
ResizeHandleRenderer(handle, rotatable, onPointerDown, getCursor)
)}
`;
}