From 8bd4cb850af1734f2763f5cf6111112c03f5b663 Mon Sep 17 00:00:00 2001 From: regischen Date: Wed, 8 Nov 2023 14:50:34 +0800 Subject: [PATCH 01/13] fix(edgeless): auto connect for ref block --- packages/blocks/src/_common/utils/model.ts | 2 + .../edgeless-auto-connect-line.ts | 24 ++- .../auto-connect/edgeless-index-label.ts | 146 ++++++++++++++---- .../block-portal/edgeless-block-portal.ts | 89 +++++++++-- 4 files changed, 216 insertions(+), 45 deletions(-) diff --git a/packages/blocks/src/_common/utils/model.ts b/packages/blocks/src/_common/utils/model.ts index 6abb0093ea75..1d4cc3822c70 100644 --- a/packages/blocks/src/_common/utils/model.ts +++ b/packages/blocks/src/_common/utils/model.ts @@ -28,6 +28,7 @@ import type { ParagraphBlockSchema, SurfaceBlockModel, SurfaceBlockSchema, + SurfaceRefBlockModel, } from '../../index.js'; export type BlockModels = { @@ -44,6 +45,7 @@ export type BlockModels = { 'affine:data-view': DataViewBlockModel; 'affine:bookmark': BookmarkBlockModel; 'affine:attachment': AttachmentBlockModel; + 'affine:surface-ref': SurfaceRefBlockModel; }; export type BlockSchemas = { diff --git a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts index 61be31d243ac..8beb1bc3b4b0 100644 --- a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts +++ b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts @@ -4,13 +4,12 @@ import { customElement, property } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; import { styleMap } from 'lit/directives/style-map.js'; -import { EdgelessBlockType } from '../../../../surface-block/edgeless-types.js'; import { Bound, type IVec, Vec } from '../../../../surface-block/index.js'; import type { SurfaceBlockComponent } from '../../../../surface-block/surface-block.js'; import { isNoteBlock } from '../../utils/query.js'; +import type { AutoConnectElement } from '../block-portal/edgeless-block-portal.js'; const EXPAND_OFFSET = 20; -const { NOTE } = EdgelessBlockType; @customElement('edgeless-auto-connect-line') export class EdgelessAutoConnectLine extends WithDisposable(LitElement) { @@ -28,6 +27,19 @@ export class EdgelessAutoConnectLine extends WithDisposable(LitElement) { @property({ attribute: false }) show = false; + @property({ attribute: false }) + elementsMap!: Map; + + private _getElementsAndCounts() { + const elements: AutoConnectElement[] = []; + const counts: number[] = []; + for (const [key, value] of this.elementsMap.entries()) { + elements.push(key); + counts.push(value); + } + return { elements, counts }; + } + protected override firstUpdated(): void { const { _disposables, surface } = this; _disposables.add( @@ -49,11 +61,11 @@ export class EdgelessAutoConnectLine extends WithDisposable(LitElement) { if (!this.show) return nothing; const { viewport } = this.surface; - const notes = this.surface.getBlocks(NOTE).filter(note => !note.hidden); + const { elements } = this._getElementsAndCounts(); const points: [IVec, IVec][] = []; - for (let i = 1; i < notes.length; i++) { - const last = notes[i - 1]; - const current = notes[i]; + for (let i = 1; i < elements.length; i++) { + const last = elements[i - 1]; + const current = elements[i]; const lastBound = Bound.deserialize(last.xywh); const currentBound = Bound.deserialize(current.xywh); const start = viewport.toViewCoord(lastBound.center[0], lastBound.maxY); diff --git a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts index 7ffe24035dad..aa3dafb2efff 100644 --- a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts +++ b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts @@ -8,10 +8,10 @@ import { AutoConnectLeftIcon, AutoConnectRightIcon, } from '../../../../_common/icons/edgeless.js'; -import type { NoteBlockModel } from '../../../../models.js'; import { Bound } from '../../../../surface-block/index.js'; import type { SurfaceBlockComponent } from '../../../../surface-block/surface-block.js'; import { isNoteBlock } from '../../utils/query.js'; +import type { AutoConnectElement } from '../block-portal/edgeless-block-portal.js'; @customElement('edgeless-index-label') export class EdgelessIndexLabel extends WithDisposable(ShadowlessElement) { @@ -72,7 +72,7 @@ export class EdgelessIndexLabel extends WithDisposable(ShadowlessElement) { show = false; @property({ attribute: false }) - notes: NoteBlockModel[] = []; + elementsMap!: Map; @state() private _index = -1; @@ -140,38 +140,48 @@ export class EdgelessIndexLabel extends WithDisposable(ShadowlessElement) { this.style.zIndex = '1'; } + private _getElementsAndCounts() { + const elements: AutoConnectElement[] = []; + const counts: number[] = []; + for (const [key, value] of this.elementsMap.entries()) { + elements.push(key); + counts.push(value); + } + return { elements, counts }; + } + private _navigateToNext() { - const { notes } = this; - if (this._index >= notes.length - 1) return; + const { elements } = this._getElementsAndCounts(); + if (this._index >= elements.length - 1) return; this._index = this._index + 1; - const note = notes[this._index]; - const bound = Bound.deserialize(note.xywh); + const element = elements[this._index]; + const bound = Bound.deserialize(element.xywh); this.surface.edgeless.selectionManager.setSelection({ - elements: [note.id], + elements: [element.id], editing: false, }); this.surface.viewport.setViewportByBound(bound, [80, 80, 80, 80], true); } private _navigateToPrev() { - const { notes } = this; + const { elements } = this._getElementsAndCounts(); if (this._index <= 0) return; this._index = this._index - 1; - const note = notes[this._index]; - const bound = Bound.deserialize(note.xywh); + const element = elements[this._index]; + const bound = Bound.deserialize(element.xywh); this.surface.edgeless.selectionManager.setSelection({ - elements: [note.id], + elements: [element.id], editing: false, }); this.surface.viewport.setViewportByBound(bound, [80, 80, 80, 80], true); } - private _NavigatorComponent(notes: NoteBlockModel[]) { + private _NavigatorComponent(elements: AutoConnectElement[]) { const { viewport } = this.surface; const { zoom } = viewport; const classname = `navigator ${this._index >= 0 ? 'show' : 'hidden'}`; - const note = notes[this._index]; - const bound = Bound.deserialize(note.xywh); + const element = elements[this._index]; + const bound = Bound.deserialize(element.xywh); const [left, right] = viewport.toViewCoord(bound.x, bound.y); const [width, height] = [bound.w * zoom, bound.h * zoom]; const navigatorStyle = styleMap({ @@ -196,30 +206,112 @@ export class EdgelessIndexLabel extends WithDisposable(ShadowlessElement) { const { viewport } = this.surface; const { zoom } = viewport; - const { notes } = this; + const { elements, counts } = this._getElementsAndCounts(); + let index = 0; return html`${repeat( - notes, - note => note.id, - (note, index) => { - const bound = Bound.deserialize(note.xywh); + elements, + element => element.id, + (element, i) => { + const bound = Bound.deserialize(element.xywh); const [left, right] = viewport.toViewCoord(bound.x, bound.y); const [width, height] = [bound.w * zoom, bound.h * zoom]; + const iconWidth = 24; const style = styleMap({ + width: '44px', + maxWidth: '44px', + height: iconWidth + 'px', position: 'absolute', - transform: `translate(${left + width / 2 - 26 / 2}px, ${ + transform: `translate(${left + width / 2 - 44 / 2}px, ${ right + height - 14 }px)`, + display: 'flex', + justifyContent: 'center', + alignItems: 'center', }); - return html` -
- ${index + 1} -
- `; + const components = []; + const count = counts[i]; + + function calculatePosition(gap: number) { + const positions = []; + if (count === 1) { + positions.push([0, 10]); + return positions; + } + const middleIndex = (count - 1) / 2; + const isEven = count % 2 === 0; + const middleOffset = (gap + iconWidth) / 2; + function getSign(num: number) { + return num - middleIndex > 0 ? 1 : -1; + } + for (let j = 0; j < count; j++) { + let left = 10; + if (isEven) { + if (Math.abs(j - middleIndex) < 1 && isEven) { + left = 10 + middleOffset * getSign(j); + } else { + left = + 10 + + ((Math.ceil(Math.abs(j - middleIndex)) - 1) * (gap + 24) + + middleOffset) * + getSign(j); + } + } else { + const offset = gap + iconWidth; + left = + 10 + Math.ceil(Math.abs(j - middleIndex)) * offset * getSign(j); + } + positions.push([0, left]); + } + + return positions; + } + const initGap = 24 / count - 24; + const positions = calculatePosition(initGap); + for (let j = 0; j < count; j++) { + index++; + components.push(html` +
+ ${index} +
+ `); + } + + function updateChildrenPosition(e: MouseEvent, positions: number[][]) { + if (!e.target) return; + const children = (e.target).children; + (Array.from(children)).forEach((c, index) => { + c.style.top = positions[index][0] + 'px'; + c.style.left = positions[index][1] + 'px'; + }); + } + + return html`
{ + const positions = calculatePosition(5); + updateChildrenPosition(e, positions); + }} + @mouseleave=${(e: MouseEvent) => { + const positions = calculatePosition(initGap); + updateChildrenPosition(e, positions); + }} + > + ${components} +
`; } )} - ${this._index >= 0 && this._index < notes.length - ? this._NavigatorComponent(notes) + ${this._index >= 0 && this._index < elements.length + ? this._NavigatorComponent(elements) : nothing} `; } } diff --git a/packages/blocks/src/page-block/edgeless/components/block-portal/edgeless-block-portal.ts b/packages/blocks/src/page-block/edgeless/components/block-portal/edgeless-block-portal.ts index 103bca3e4e32..15e46090d38e 100644 --- a/packages/blocks/src/page-block/edgeless/components/block-portal/edgeless-block-portal.ts +++ b/packages/blocks/src/page-block/edgeless/components/block-portal/edgeless-block-portal.ts @@ -21,13 +21,22 @@ import { EDGELESS_BLOCK_CHILD_PADDING, } from '../../../../_common/consts.js'; import { delayCallback } from '../../../../_common/utils/event.js'; +import { matchFlavours } from '../../../../_common/utils/index.js'; import type { TopLevelBlockModel } from '../../../../_common/utils/types.js'; +import type { FrameBlockModel } from '../../../../models.js'; +import type { NoteBlockModel } from '../../../../note-block/index.js'; import { EdgelessBlockType } from '../../../../surface-block/edgeless-types.js'; +import type { GroupElement } from '../../../../surface-block/index.js'; import { almostEqual, Bound } from '../../../../surface-block/index.js'; import type { EdgelessPageBlockComponent } from '../../edgeless-page-block.js'; import { NoteResizeObserver } from '../../utils/note-resize-observer.js'; import { getBackgroundGrid, isNoteBlock } from '../../utils/query.js'; +export type AutoConnectElement = + | NoteBlockModel + | FrameBlockModel + | GroupElement; + const { NOTE, IMAGE, FRAME } = EdgelessBlockType; const portalMap = { @@ -56,6 +65,8 @@ export class EdgelessBlockPortalContainer extends WithDisposable( private _noteResizeObserver = new NoteResizeObserver(); + private _surfaceRefReferenceSet = new Set(); + private _initNoteHeightUpdate() { const { page } = this.edgeless; assertExists(page.root); @@ -104,7 +115,34 @@ export class EdgelessBlockPortalContainer extends WithDisposable( ); }; + private _updateReference() { + const { _surfaceRefReferenceSet, edgeless } = this; + edgeless.surface.getBlocks(NOTE).forEach(note => { + note.children.forEach(model => { + if (matchFlavours(model, ['affine:surface-ref'])) { + _surfaceRefReferenceSet.add(model.reference); + } + }); + }); + } + + private _updateAutoConnect() { + const { edgeless } = this; + const { elements } = edgeless.selectionManager; + if ( + !edgeless.selectionManager.editing && + elements.length === 1 && + (isNoteBlock(elements[0]) || + this._surfaceRefReferenceSet.has(elements[0].id)) + ) { + this._showAutoConnect = true; + } else { + this._showAutoConnect = false; + } + } + override firstUpdated() { + this._updateReference(); const { _disposables, edgeless } = this; const { page } = edgeless; @@ -187,19 +225,24 @@ export class EdgelessBlockPortalContainer extends WithDisposable( ); _disposables.add( - edgeless.selectionManager.slots.updated.on(() => { - const { elements } = edgeless.selectionManager; + page.slots.blockUpdated.on(({ type, flavour }) => { if ( - !edgeless.selectionManager.editing && - elements.length === 1 && - isNoteBlock(elements[0]) + (type === 'add' || type === 'delete') && + (flavour === 'affine:surface-ref' || flavour === NOTE) ) { - this._showAutoConnect = true; - } else { - this._showAutoConnect = false; + requestAnimationFrame(() => { + this._updateReference(); + this._updateAutoConnect(); + }); } }) ); + + _disposables.add( + edgeless.selectionManager.slots.updated.on(() => { + this._updateAutoConnect(); + }) + ); } override render() { @@ -212,12 +255,35 @@ export class EdgelessBlockPortalContainer extends WithDisposable( const blocks = [...notes, ...images].sort(surface.compare); const { readonly } = this.edgeless.page; - const showedNotes = surface.getBlocks(NOTE).filter(note => !note.hidden); + const autoConnectedBlocks = new Map(); + + notes.forEach(note => { + if (isNoteBlock(note) && !note.hidden) { + autoConnectedBlocks.set(note, 1); + } + note.children.forEach(model => { + if (matchFlavours(model, ['affine:surface-ref'])) { + const reference = surface.pickById( + model.reference + ) as AutoConnectElement; + if (!autoConnectedBlocks.has(reference)) { + autoConnectedBlocks.set(reference, 1); + } else { + autoConnectedBlocks.set( + reference, + autoConnectedBlocks.get(reference)! + 1 + ); + } + } + }); + }); + return html`
@@ -248,13 +314,12 @@ export class EdgelessBlockPortalContainer extends WithDisposable( - - + `; } } From 1a3ec8253b12bfba02b68d4c58f5ff3b486116b3 Mon Sep 17 00:00:00 2001 From: regischen Date: Wed, 8 Nov 2023 17:16:44 +0800 Subject: [PATCH 02/13] fix: auto connect ref-block --- .../edgeless-auto-connect-line.ts | 5 +- .../block-portal/edgeless-block-portal.ts | 26 ++++- .../component-toolbar/component-toolbar.ts | 58 ++++++++-- .../rects/edgeless-selected-rect.ts | 105 ++---------------- 4 files changed, 82 insertions(+), 112 deletions(-) diff --git a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts index 8beb1bc3b4b0..9a100a7f0cf2 100644 --- a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts +++ b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts @@ -9,7 +9,7 @@ import type { SurfaceBlockComponent } from '../../../../surface-block/surface-bl import { isNoteBlock } from '../../utils/query.js'; import type { AutoConnectElement } from '../block-portal/edgeless-block-portal.js'; -const EXPAND_OFFSET = 20; +const EXPAND_OFFSET = 40; @customElement('edgeless-auto-connect-line') export class EdgelessAutoConnectLine extends WithDisposable(LitElement) { @@ -118,6 +118,9 @@ export class EdgelessAutoConnectLine extends WithDisposable(LitElement) { EXPAND_OFFSET / 2, ]); + if (newStart.every(a => isNaN(a)) || newEnd.every(a => isNaN(a))) + return nothing; + return svg` diff --git a/packages/blocks/src/page-block/edgeless/components/block-portal/edgeless-block-portal.ts b/packages/blocks/src/page-block/edgeless/components/block-portal/edgeless-block-portal.ts index 15e46090d38e..6825b1a3b6b8 100644 --- a/packages/blocks/src/page-block/edgeless/components/block-portal/edgeless-block-portal.ts +++ b/packages/blocks/src/page-block/edgeless/components/block-portal/edgeless-block-portal.ts @@ -8,6 +8,7 @@ import '../rects/edgeless-dragging-area-rect.js'; import '../note-status/index.js'; import '../../components/auto-connect/edgeless-index-label.js'; import '../../components/auto-connect/edgeless-auto-connect-line.js'; +import '../component-toolbar/component-toolbar.js'; import { assertExists, throttle } from '@blocksuite/global/utils'; import { ShadowlessElement, WithDisposable } from '@blocksuite/lit'; @@ -61,6 +62,9 @@ export class EdgelessBlockPortalContainer extends WithDisposable( @state() private _showAutoConnect = false; + @state() + private _toolbarVisible = false; + private _cancelRestoreWillchange: (() => void) | null = null; private _noteResizeObserver = new NoteResizeObserver(); @@ -239,7 +243,12 @@ export class EdgelessBlockPortalContainer extends WithDisposable( ); _disposables.add( - edgeless.selectionManager.slots.updated.on(() => { + edgeless.selectionManager.slots.updated.on(e => { + if (e.elements.length === 0 || e.editing) { + this._toolbarVisible = false; + } else { + this._toolbarVisible = true; + } this._updateAutoConnect(); }) ); @@ -248,7 +257,7 @@ export class EdgelessBlockPortalContainer extends WithDisposable( override render() { const { edgeless } = this; - const { surface } = edgeless; + const { surface, page } = edgeless; if (!surface) return nothing; const notes = surface.getBlocks(NOTE); const images = surface.getBlocks(IMAGE); @@ -314,12 +323,23 @@ export class EdgelessBlockPortalContainer extends WithDisposable( + + { + this._toolbarVisible = v; + }} + > - + ${this._toolbarVisible && !page.readonly + ? html` + ` + : nothing} `; } } diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index 3e07fc5368e9..a7d399345c39 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -31,11 +31,13 @@ import { GROUP_ROOT } from '../../../../surface-block/elements/group/consts.js'; import type { GroupElement } from '../../../../surface-block/index.js'; import { type BrushElement, + clamp, type ConnectorElement, type ShapeElement, type TextElement, } from '../../../../surface-block/index.js'; import type { EdgelessPageBlockComponent } from '../../edgeless-page-block.js'; +import { edgelessElementsBound } from '../../utils/bound-utils.js'; import { isFrameBlock, isImageBlock, isNoteBlock } from '../../utils/query.js'; type CategorizedElements = { @@ -52,16 +54,6 @@ type CategorizedElements = { @customElement('edgeless-component-toolbar') export class EdgelessComponentToolbar extends WithDisposable(LitElement) { static override styles = css` - :host { - display: block; - position: absolute; - user-select: none; - } - - :host([data-show]) { - display: block; - } - .edgeless-component-toolbar-container { display: flex; align-items: center; @@ -220,6 +212,18 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { ]).forEach(slot => this._disposables.add(slot.on(this._updateOnSelectedChange)) ); + + this.style.position = 'absolute'; + this.style.zIndex = '1'; + } + + protected override firstUpdated() { + const { _disposables } = this; + _disposables.add( + this.surface.viewport.slots.viewportUpdated.on(() => + this._updatePosition() + ) + ); } private _getCreateGroupButton() { @@ -246,7 +250,41 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { >`; } + private async _updatePosition() { + await this.updateComplete; + const { selectionManager } = this.edgeless; + + const bound = edgelessElementsBound(selectionManager.elements); + + const { viewport } = this.edgeless.surface; + const { width, height } = viewport; + const [x, y] = viewport.toViewCoord(bound.x, bound.y); + + const [right, bottom] = viewport.toViewCoord(bound.maxX, bound.maxY); + const rect = this.getBoundingClientRect(); + + if (x >= width || right <= 0 || y >= height || bottom <= 0) { + this.style.left = (right <= 0 ? x - rect.width : x) + 'px'; + this.style.top = (bottom <= 0 ? y - rect.height : y) + 'px'; + return; + } + + let offset = 34; + if (this.selection.elements.find(ele => isFrameBlock(ele))) { + offset += 10; + } + let top = y - rect.height - offset; + top < 0 && (top = y + bound.h * viewport.zoom + offset); + + const left = clamp(x, 10, width - rect.width - 10); + top = clamp(top, 10, height - rect.height - 100); + + this.style.left = left + 'px'; + this.style.top = top + 'px'; + } + override render() { + this._updatePosition(); const groupedSelected = this._groupSelected(); const { edgeless, selection } = this; const { shape, brush, connector, note, text, frame, group } = diff --git a/packages/blocks/src/page-block/edgeless/components/rects/edgeless-selected-rect.ts b/packages/blocks/src/page-block/edgeless/components/rects/edgeless-selected-rect.ts index 8e0f42efd8af..f4806a7170be 100644 --- a/packages/blocks/src/page-block/edgeless/components/rects/edgeless-selected-rect.ts +++ b/packages/blocks/src/page-block/edgeless/components/rects/edgeless-selected-rect.ts @@ -1,15 +1,13 @@ -import '../component-toolbar/component-toolbar.js'; import '../connector/connector-handle.js'; import '../auto-complete/edgeless-auto-complete.js'; import { WithDisposable } from '@blocksuite/lit'; import { css, html, LitElement, nothing } from 'lit'; -import { customElement, property, query, state } from 'lit/decorators.js'; +import { customElement, property, state } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; import { stopPropagation } from '../../../../_common/utils/event.js'; import { pick } from '../../../../_common/utils/iterable.js'; -import { clamp } from '../../../../_common/utils/math.js'; import type { EdgelessElement, IPoint, @@ -33,7 +31,6 @@ import { } from '../../../../surface-block/index.js'; import { getElementsWithoutGroup } from '../../../../surface-block/managers/group-manager.js'; import type { EdgelessPageBlockComponent } from '../../edgeless-page-block.js'; -import { edgelessElementsBound } from '../../utils/bound-utils.js'; import { NOTE_MIN_HEIGHT } from '../../utils/consts.js'; import { getSelectableBounds, @@ -43,7 +40,6 @@ import { isNoteBlock, isPhasorElement, } from '../../utils/query.js'; -import type { EdgelessComponentToolbar } from '../component-toolbar/component-toolbar.js'; import { HandleDirection } from '../resize/resize-handles.js'; import { ResizeHandles, type ResizeMode } from '../resize/resize-handles.js'; import { HandleResizeManager } from '../resize/resize-manager.js'; @@ -296,12 +292,6 @@ export class EdgelessSelectedRect extends WithDisposable(LitElement) { @property({ attribute: false }) edgeless!: EdgelessPageBlockComponent; - @query('edgeless-component-toolbar') - private _componentToolbar!: EdgelessComponentToolbar; - - @query('.affine-edgeless-selected-rect') - private _selectedRectEl!: HTMLDivElement; - @state() private _selectedRect: SelectedRect = { width: 0, @@ -314,17 +304,11 @@ export class EdgelessSelectedRect extends WithDisposable(LitElement) { rotate: 0, }; - @state() - private _toolbarVisible = false; + @property({ attribute: false }) + toolbarVisible = false; - @state() - private _toolbarPosition: { - x: number; - y: number; - } = { - x: 0, - y: 0, - }; + @property({ attribute: false }) + setToolbarVisible!: (visible: boolean) => void; private _resizeManager: HandleResizeManager; private _cursorRotate = 0; @@ -404,7 +388,7 @@ export class EdgelessSelectedRect extends WithDisposable(LitElement) { } private _onDragStart = () => { - this._toolbarVisible = false; + this.setToolbarVisible(false); this._updateResizeManagerState(false); }; @@ -506,7 +490,7 @@ export class EdgelessSelectedRect extends WithDisposable(LitElement) { private _onDragEnd = () => { this._updateCursor(false); - this._toolbarVisible = true; + this.setToolbarVisible(true); }; private _updateCursor = ( @@ -563,53 +547,6 @@ export class EdgelessSelectedRect extends WithDisposable(LitElement) { this.slots.cursorUpdated.emit(cursor); }; - private async _updateToolbarPosition() { - if ( - !this._toolbarVisible || - !this._shouldRenderSelection() || - this.page.readonly - ) - return; - - if (!this._selectedRectEl || !this._componentToolbar) { - await this.updateComplete; - } - - if (this._componentToolbar.isUpdatePending) - await this._componentToolbar.updateComplete; - - const componentToolbar = this._componentToolbar; - const bound = edgelessElementsBound(this.selection.elements); - - const { viewport } = this.edgeless.surface; - const { width, height } = viewport; - const [x, y] = viewport.toViewCoord(bound.x, bound.y); - const [right, bottom] = viewport.toViewCoord(bound.maxX, bound.maxY); - const rect = componentToolbar.getBoundingClientRect(); - if (x >= width || right <= 0 || y >= height || bottom <= 0) { - this._toolbarPosition = { - x: right <= 0 ? x - rect.width : x, - y: y >= height ? bottom : y, - }; - return; - } - - let offset = 34; - if (this.selection.elements.find(ele => isFrameBlock(ele))) { - offset += 10; - } - let top = y - rect.height - offset; - top < 0 && (top = y + bound.h * viewport.zoom + offset); - - const left = clamp(x, 10, width - rect.width - 10); - top = clamp(top, 10, height - rect.height - 100); - - this._toolbarPosition = { - x: left, - y: top, - }; - } - private _updateSelectedRect() { const { surface, zoom, selection } = this; @@ -677,12 +614,6 @@ export class EdgelessSelectedRect extends WithDisposable(LitElement) { private _updateOnSelectionChange = () => { this._updateSelectedRect(); this._updateResizeManagerState(true); - - if (this.selection.editing) { - this._toolbarVisible = false; - } else { - this._toolbarVisible = true; - } }; private _updateOnElementChange = ( @@ -729,17 +660,6 @@ export class EdgelessSelectedRect extends WithDisposable(LitElement) { ); } - protected override updated( - _changedProperties: Map - ): void { - if ( - _changedProperties.has('_selectedRect') || - (_changedProperties.has('_toolbarVisible') && this._toolbarVisible) - ) { - this._updateToolbarPosition(); - } - } - private _canAutoComplete() { return ( this.selection.elements.length === 1 && @@ -760,7 +680,6 @@ export class EdgelessSelectedRect extends WithDisposable(LitElement) { resizeMode, _resizeManager, _selectedRect, - _toolbarPosition, _updateCursor, } = this; @@ -820,16 +739,6 @@ export class EdgelessSelectedRect extends WithDisposable(LitElement) { > ${resizeHandles} ${connectorHandle}
- ${this._toolbarVisible && !page.readonly - ? html` - ` - : nothing} `; } } From f979e889f3d45420ceb5055238c4e109bd2a821d Mon Sep 17 00:00:00 2001 From: Yifeng Wang Date: Wed, 8 Nov 2023 18:16:47 +0800 Subject: [PATCH 03/13] style: naming --- .../component-toolbar/component-toolbar.ts | 67 +++++++++---------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index a7d399345c39..db7ee3bc8806 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -103,7 +103,7 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { return result as CategorizedElements; } - private _getShapeButton(shapeElements?: ShapeElement[]) { + private _ShapeButton(shapeElements?: ShapeElement[]) { const shapeButton = shapeElements?.length ? html` `; } - private _getCreateFrameButton() { + private _CreateFrameButton() { return html``; } - private _getReleaseFromGroupButton() { + private _ReleaseFromGroupButton() { return html``; } - private _getAlignButton() { + private _AlignButton() { return html``; } + private _Divider() { + return html``; + } + private async _updatePosition() { - await this.updateComplete; + // await this.updateComplete; const { selectionManager } = this.edgeless; const bound = edgelessElementsBound(selectionManager.elements); @@ -299,35 +303,28 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { const buttons = selectedAtLeastTwoTypes ? [] : [ - this._getShapeButton(shape), - this._getBrushButton(brush), - this._getConnectorButton(connector), - this._getNoteButton(note), - this._getTextButton(text), - this._getFrameButton(frame), - this._getGroupButton(group), + this._ShapeButton(shape), + this._BrushButton(brush), + this._ConnectorButton(connector), + this._NoteButton(note), + this._TextButton(text), + this._FrameButton(frame), + this._GroupButton(group), ].filter(b => !!b && b !== nothing); if (elements.length > 1) { - buttons.unshift( - html`` - ); - buttons.unshift(this._getAlignButton()); - buttons.unshift( - html`` - ); - buttons.unshift(this._getCreateGroupButton()); - buttons.unshift( - html`` - ); - buttons.unshift(this._getCreateFrameButton()); + buttons.unshift(this._Divider()); + buttons.unshift(this._AlignButton()); + buttons.unshift(this._Divider()); + buttons.unshift(this._CreateGroupButton()); + buttons.unshift(this._Divider()); + buttons.unshift(this._CreateFrameButton()); } + if (elements.length === 1) { if (this.surface.getGroupParent(selection.firstElement) !== GROUP_ROOT) { - buttons.unshift( - html`` - ); - buttons.unshift(this._getReleaseFromGroupButton()); + buttons.unshift(this._Divider()); + buttons.unshift(this._ReleaseFromGroupButton()); } } From 68e295bce2193a342ef72feec263a17e63dc3739 Mon Sep 17 00:00:00 2001 From: regischen Date: Fri, 10 Nov 2023 10:23:37 +0800 Subject: [PATCH 04/13] fix: not udpate state in render --- .../component-toolbar/component-toolbar.ts | 76 +++++++++++++------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index db7ee3bc8806..51ab58239173 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -14,7 +14,15 @@ import './align-button.js'; import { WithDisposable } from '@blocksuite/lit'; import { baseTheme } from '@toeverything/theme'; -import { css, html, LitElement, nothing, unsafeCSS } from 'lit'; +import { + css, + html, + LitElement, + nothing, + type PropertyValueMap, + type PropertyValues, + unsafeCSS, +} from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { join } from 'lit/directives/join.js'; @@ -73,6 +81,12 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { @property({ attribute: false }) edgeless!: EdgelessPageBlockComponent; + @property({ attribute: false }) + left = 0; + + @property({ attribute: false }) + top = 0; + get page() { return this.edgeless.page; } @@ -212,9 +226,6 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { ]).forEach(slot => this._disposables.add(slot.on(this._updateOnSelectedChange)) ); - - this.style.position = 'absolute'; - this.style.zIndex = '1'; } protected override firstUpdated() { @@ -254,8 +265,17 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { return html``; } - private async _updatePosition() { - // await this.updateComplete; + protected override updated(_changedProperties: PropertyValues): void { + // if (_changedProperties.has('left') || _changedProperties.has('top')) { + const [left, top] = this._updatePosition(); + if (this.left !== left || this.top !== top) { + this.left = left; + this.top = top; + } + // } + } + + private _updatePosition() { const { selectionManager } = this.edgeless; const bound = edgelessElementsBound(selectionManager.elements); @@ -266,25 +286,23 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { const [right, bottom] = viewport.toViewCoord(bound.maxX, bound.maxY); const rect = this.getBoundingClientRect(); - + let left, top; if (x >= width || right <= 0 || y >= height || bottom <= 0) { - this.style.left = (right <= 0 ? x - rect.width : x) + 'px'; - this.style.top = (bottom <= 0 ? y - rect.height : y) + 'px'; - return; + left = right <= 0 ? x - rect.width : x; + top = bottom <= 0 ? y - rect.height : y; + return [left, top]; } let offset = 34; if (this.selection.elements.find(ele => isFrameBlock(ele))) { offset += 10; } - let top = y - rect.height - offset; + top = y - rect.height - offset; top < 0 && (top = y + bound.h * viewport.zoom + offset); - const left = clamp(x, 10, width - rect.width - 10); + left = clamp(x, 10, width - rect.width - 10); top = clamp(top, 10, height - rect.height - 100); - - this.style.left = left + 'px'; - this.style.top = top + 'px'; + return [left, top]; } override render() { @@ -339,16 +357,24 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { ); } - return html`
- ${join(buttons, () => '')} - -
`; + return html` +
+ ${join(buttons, () => '')} + +
`; } } declare global { From 90c14a4ddc243343d9b4d3c32b8ae585472decb0 Mon Sep 17 00:00:00 2001 From: regischen Date: Fri, 10 Nov 2023 10:25:05 +0800 Subject: [PATCH 05/13] fix: lint --- .../edgeless/components/component-toolbar/component-toolbar.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index 51ab58239173..2728d7830ccf 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -19,7 +19,6 @@ import { html, LitElement, nothing, - type PropertyValueMap, type PropertyValues, unsafeCSS, } from 'lit'; From 5e477b70aab44e15a7a430401daa47dba23f6d1a Mon Sep 17 00:00:00 2001 From: regischen Date: Fri, 10 Nov 2023 11:07:28 +0800 Subject: [PATCH 06/13] fix: lit warning --- .../component-toolbar/component-toolbar.ts | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index 2728d7830ccf..4dc42c658f65 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -201,38 +201,31 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { private _updateOnSelectedChange = (element: string | { id: string }) => { const id = typeof element === 'string' ? element : element.id; - if (this.selection.isSelected(id)) { this.requestUpdate(); } }; - override connectedCallback(): void { - super.connectedCallback(); + protected override firstUpdated() { + const { _disposables, edgeless, surface } = this; + _disposables.add( + surface.viewport.slots.viewportUpdated.on(() => this._updatePosition()) + ); - this._disposables.add( + _disposables.add( this.selection.slots.updated.on(() => { this.requestUpdate(); }) ); - this._disposables.add( - this.edgeless.page.slots.blockUpdated.on(this._updateOnSelectedChange) - ); + pickValues(this.edgeless.surface.slots, [ 'elementAdded', 'elementRemoved', 'elementUpdated', - ]).forEach(slot => - this._disposables.add(slot.on(this._updateOnSelectedChange)) - ); - } + ]).forEach(slot => _disposables.add(slot.on(this._updateOnSelectedChange))); - protected override firstUpdated() { - const { _disposables } = this; _disposables.add( - this.surface.viewport.slots.viewportUpdated.on(() => - this._updatePosition() - ) + edgeless.page.slots.yBlockUpdated.on(this._updateOnSelectedChange) ); } @@ -264,14 +257,13 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { return html``; } - protected override updated(_changedProperties: PropertyValues): void { - // if (_changedProperties.has('left') || _changedProperties.has('top')) { + protected override async updated(_changedProperties: PropertyValues) { const [left, top] = this._updatePosition(); if (this.left !== left || this.top !== top) { + await this.updateComplete; this.left = left; this.top = top; } - // } } private _updatePosition() { From d898dc7b5f8d086511888b11e04c49a0e1a4362f Mon Sep 17 00:00:00 2001 From: regischen Date: Fri, 10 Nov 2023 11:23:32 +0800 Subject: [PATCH 07/13] fix: remove side effect in render --- .../edgeless/components/component-toolbar/component-toolbar.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index 4dc42c658f65..3eec2afd613f 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -297,7 +297,6 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { } override render() { - this._updatePosition(); const groupedSelected = this._groupSelected(); const { edgeless, selection } = this; const { shape, brush, connector, note, text, frame, group } = From df8505b0eaf955df1bc9222bcfde3185b3265934 Mon Sep 17 00:00:00 2001 From: regischen Date: Fri, 10 Nov 2023 11:37:06 +0800 Subject: [PATCH 08/13] fix: change method name --- .../components/component-toolbar/component-toolbar.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index 3eec2afd613f..b8081d340a72 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -209,7 +209,7 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { protected override firstUpdated() { const { _disposables, edgeless, surface } = this; _disposables.add( - surface.viewport.slots.viewportUpdated.on(() => this._updatePosition()) + surface.viewport.slots.viewportUpdated.on(() => this._computePosition()) ); _disposables.add( @@ -258,7 +258,7 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { } protected override async updated(_changedProperties: PropertyValues) { - const [left, top] = this._updatePosition(); + const [left, top] = this._computePosition(); if (this.left !== left || this.top !== top) { await this.updateComplete; this.left = left; @@ -266,7 +266,7 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { } } - private _updatePosition() { + private _computePosition() { const { selectionManager } = this.edgeless; const bound = edgelessElementsBound(selectionManager.elements); From 7eaa728de1b3ea702da6a2d421aae23cda685778 Mon Sep 17 00:00:00 2001 From: regischen Date: Fri, 10 Nov 2023 11:41:08 +0800 Subject: [PATCH 09/13] fix: update state on viewport update slot --- .../component-toolbar/component-toolbar.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index b8081d340a72..e6e42e8c328b 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -209,7 +209,11 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { protected override firstUpdated() { const { _disposables, edgeless, surface } = this; _disposables.add( - surface.viewport.slots.viewportUpdated.on(() => this._computePosition()) + surface.viewport.slots.viewportUpdated.on(() => { + const [left, top] = this._computePosition(); + this.left = left; + this.top = top; + }) ); _disposables.add( @@ -259,11 +263,10 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { protected override async updated(_changedProperties: PropertyValues) { const [left, top] = this._computePosition(); - if (this.left !== left || this.top !== top) { - await this.updateComplete; - this.left = left; - this.top = top; - } + + await this.updateComplete; + this.left = left; + this.top = top; } private _computePosition() { From f99cbb4ff4c5d03a160f55a07cb3419de901052d Mon Sep 17 00:00:00 2001 From: regischen Date: Fri, 10 Nov 2023 11:42:08 +0800 Subject: [PATCH 10/13] fix: use state not property --- .../components/component-toolbar/component-toolbar.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index e6e42e8c328b..ab3e1c76b532 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -22,7 +22,7 @@ import { type PropertyValues, unsafeCSS, } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; +import { customElement, property, state } from 'lit/decorators.js'; import { join } from 'lit/directives/join.js'; import { stopPropagation } from '../../../../_common/utils/event.js'; @@ -80,10 +80,10 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { @property({ attribute: false }) edgeless!: EdgelessPageBlockComponent; - @property({ attribute: false }) + @state() left = 0; - @property({ attribute: false }) + @state() top = 0; get page() { From b50a714c7b7d0af1d2c1acb2fca2bffeac7dc620 Mon Sep 17 00:00:00 2001 From: regischen Date: Fri, 10 Nov 2023 11:44:40 +0800 Subject: [PATCH 11/13] fix: remove unused property --- .../edgeless/components/component-toolbar/component-toolbar.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts index ab3e1c76b532..8d41f04d3e37 100644 --- a/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts +++ b/packages/blocks/src/page-block/edgeless/components/component-toolbar/component-toolbar.ts @@ -147,7 +147,6 @@ export class EdgelessComponentToolbar extends WithDisposable(LitElement) { .elements=${connectorElements} .page=${this.page} .surface=${this.surface} - .slots=${this.slots} .edgeless=${this.edgeless} > ` From 481fa21178c1ddb23e0fc435da5c9a6b0e3055b4 Mon Sep 17 00:00:00 2001 From: regischen Date: Fri, 10 Nov 2023 12:13:00 +0800 Subject: [PATCH 12/13] fix: remove isNaN test and extract functionality --- .../edgeless-auto-connect-line.ts | 3 - .../auto-connect/edgeless-index-label.ts | 74 +++++++++---------- .../blocks/src/surface-block/utils/vec.ts | 3 +- 3 files changed, 38 insertions(+), 42 deletions(-) diff --git a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts index 9a100a7f0cf2..806554855874 100644 --- a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts +++ b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-auto-connect-line.ts @@ -118,9 +118,6 @@ export class EdgelessAutoConnectLine extends WithDisposable(LitElement) { EXPAND_OFFSET / 2, ]); - if (newStart.every(a => isNaN(a)) || newEnd.every(a => isNaN(a))) - return nothing; - return svg` diff --git a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts index aa3dafb2efff..ae08a783fdd4 100644 --- a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts +++ b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts @@ -13,6 +13,39 @@ import type { SurfaceBlockComponent } from '../../../../surface-block/surface-bl import { isNoteBlock } from '../../utils/query.js'; import type { AutoConnectElement } from '../block-portal/edgeless-block-portal.js'; +function calculatePosition(gap: number, count: number, iconWidth: number) { + const positions = []; + if (count === 1) { + positions.push([0, 10]); + return positions; + } + const middleIndex = (count - 1) / 2; + const isEven = count % 2 === 0; + const middleOffset = (gap + iconWidth) / 2; + function getSign(num: number) { + return num - middleIndex > 0 ? 1 : -1; + } + for (let j = 0; j < count; j++) { + let left = 10; + if (isEven) { + if (Math.abs(j - middleIndex) < 1 && isEven) { + left = 10 + middleOffset * getSign(j); + } else { + left = + 10 + + ((Math.ceil(Math.abs(j - middleIndex)) - 1) * (gap + 24) + + middleOffset) * + getSign(j); + } + } else { + const offset = gap + iconWidth; + left = 10 + Math.ceil(Math.abs(j - middleIndex)) * offset * getSign(j); + } + positions.push([0, left]); + } + + return positions; +} @customElement('edgeless-index-label') export class EdgelessIndexLabel extends WithDisposable(ShadowlessElement) { static override styles = css` @@ -231,43 +264,8 @@ export class EdgelessIndexLabel extends WithDisposable(ShadowlessElement) { }); const components = []; const count = counts[i]; - - function calculatePosition(gap: number) { - const positions = []; - if (count === 1) { - positions.push([0, 10]); - return positions; - } - const middleIndex = (count - 1) / 2; - const isEven = count % 2 === 0; - const middleOffset = (gap + iconWidth) / 2; - function getSign(num: number) { - return num - middleIndex > 0 ? 1 : -1; - } - for (let j = 0; j < count; j++) { - let left = 10; - if (isEven) { - if (Math.abs(j - middleIndex) < 1 && isEven) { - left = 10 + middleOffset * getSign(j); - } else { - left = - 10 + - ((Math.ceil(Math.abs(j - middleIndex)) - 1) * (gap + 24) + - middleOffset) * - getSign(j); - } - } else { - const offset = gap + iconWidth; - left = - 10 + Math.ceil(Math.abs(j - middleIndex)) * offset * getSign(j); - } - positions.push([0, left]); - } - - return positions; - } const initGap = 24 / count - 24; - const positions = calculatePosition(initGap); + const positions = calculatePosition(initGap, count, iconWidth); for (let j = 0; j < count; j++) { index++; components.push(html` @@ -298,11 +296,11 @@ export class EdgelessIndexLabel extends WithDisposable(ShadowlessElement) { return html`
{ - const positions = calculatePosition(5); + const positions = calculatePosition(5, count, iconWidth); updateChildrenPosition(e, positions); }} @mouseleave=${(e: MouseEvent) => { - const positions = calculatePosition(initGap); + const positions = calculatePosition(initGap, count, iconWidth); updateChildrenPosition(e, positions); }} > diff --git a/packages/blocks/src/surface-block/utils/vec.ts b/packages/blocks/src/surface-block/utils/vec.ts index 9ba3d7aacecd..a7729a5f7385 100644 --- a/packages/blocks/src/surface-block/utils/vec.ts +++ b/packages/blocks/src/surface-block/utils/vec.ts @@ -563,7 +563,8 @@ export class Vec { }; static pointOffset = (A: IVec, B: IVec, offset: number): IVec => { - const u = Vec.uni(Vec.sub(B, A)); + let u = Vec.uni(Vec.sub(B, A)); + if (Vec.isEqual(A, B)) u = A; return Vec.add(A, Vec.mul(u, offset)); }; From da72eedfdf2dac6ad39e29393e7f6ff51b560308 Mon Sep 17 00:00:00 2001 From: Yifeng Wang Date: Fri, 10 Nov 2023 12:27:40 +0800 Subject: [PATCH 13/13] style: spacing --- .../edgeless/components/auto-connect/edgeless-index-label.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts index ae08a783fdd4..d5ab5ff87c41 100644 --- a/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts +++ b/packages/blocks/src/page-block/edgeless/components/auto-connect/edgeless-index-label.ts @@ -46,6 +46,7 @@ function calculatePosition(gap: number, count: number, iconWidth: number) { return positions; } + @customElement('edgeless-index-label') export class EdgelessIndexLabel extends WithDisposable(ShadowlessElement) { static override styles = css`