import '../buttons/tool-icon-button.js';
import './change-shape-button.js';
import './change-brush-button.js';
import './change-connector-button.js';
import './change-note-button.js';
import './change-embed-card-button.js';
import './change-text-button.js';
import './change-frame-button.js';
import './change-group-button.js';
import './add-frame-button.js';
import './add-group-button.js';
import './release-from-group-button.js';
import './more-button.js';
import './align-button.js';
import { WithDisposable } from '@blockeditor/lit';
import { baseTheme } from '@toeverything/theme';
import {
css,
html,
LitElement,
nothing,
type PropertyValues,
unsafeCSS,
} from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { join } from 'lit/directives/join.js';
import { stopPropagation } from '../../../../_common/utils/event.js';
import {
atLeastNMatches,
groupBy,
pickValues,
} from '../../../../_common/utils/iterable.js';
import type { BookmarkBlockModel } from '../../../../bookmark-block/bookmark-model.js';
import type { EmbedFigmaModel } from '../../../../embed-figma-block/embed-figma-model.js';
import type { EmbedGithubModel } from '../../../../embed-github-block/embed-github-model.js';
import type { EmbedLinkedDocModel } from '../../../../embed-linked-doc-block/embed-linked-doc-model.js';
import type { EmbedYoutubeModel } from '../../../../embed-youtube-block/embed-youtube-model.js';
import type { FrameBlockModel } from '../../../../frame-block/index.js';
import type { ImageBlockModel } from '../../../../image-block/index.js';
import type { NoteBlockModel } from '../../../../note-block/index.js';
import type {
ElementModel,
GroupElementModel,
} from '../../../../surface-block/index.js';
import {
type BrushElementModel,
clamp,
type ConnectorElementModel,
type ShapeElementModel,
type TextElementModel,
} from '../../../../surface-block/index.js';
import type { EdgelessPageBlockComponent } from '../../edgeless-page-block.js';
import { edgelessElementsBound } from '../../utils/bound-utils.js';
import {
isBookmarkBlock,
isEmbeddedBlock,
isFrameBlock,
isImageBlock,
isNoteBlock,
} from '../../utils/query.js';
type CategorizedElements = {
shape?: ShapeElementModel[];
brush?: BrushElementModel[];
text?: TextElementModel[];
group?: GroupElementModel[];
connector?: ConnectorElementModel[];
note?: NoteBlockModel[];
frame?: FrameBlockModel[];
image?: ImageBlockModel[];
embedCard?: BookmarkBlockModel[] &
EmbedGithubModel[] &
EmbedYoutubeModel[] &
EmbedFigmaModel[] &
EmbedLinkedDocModel[];
};
@customElement('edgeless-component-toolbar')
export class EdgelessComponentToolbar extends WithDisposable(LitElement) {
static override styles = css`
.edgeless-component-toolbar-container {
display: flex;
align-items: center;
height: 40px;
background: var(--affine-background-overlay-panel-color);
box-shadow: var(--affine-menu-shadow);
border-radius: 8px;
padding: 0 8px;
font-family: ${unsafeCSS(baseTheme.fontSansFamily)};
}
component-toolbar-menu-divider {
width: 4px;
margin: 0 12px;
height: 24px;
}
`;
@property({ attribute: false })
edgeless!: EdgelessPageBlockComponent;
@state()
left = 0;
@state()
top = 0;
@state()
private _showPopper = false;
get page() {
return this.edgeless.page;
}
get selection() {
return this.edgeless.service.selection;
}
get slots() {
return this.edgeless.slots;
}
get surface() {
return this.edgeless.surface;
}
private _groupSelected(): CategorizedElements {
const result = groupBy(this.selection.elements, model => {
if (isNoteBlock(model)) {
return 'note';
} else if (isFrameBlock(model)) {
return 'frame';
} else if (isImageBlock(model)) {
return 'image';
} else if (isBookmarkBlock(model) || isEmbeddedBlock(model)) {
return 'embedCard';
}
return (model as ElementModel).type;
});
return result as CategorizedElements;
}
private _ShapeButton(shapeElements?: ShapeElementModel[]) {
const shapeButton = shapeElements?.length
? html`