mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-15 05:37:32 +00:00
refactor(editor): extract edgeless text (#9375)
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { EdgelessTextBlockSpec } from '@blocksuite/affine-block-edgeless-text';
|
||||
import { FrameBlockSpec } from '@blocksuite/affine-block-frame';
|
||||
import { LatexBlockSpec } from '@blocksuite/affine-block-latex';
|
||||
import { EdgelessSurfaceBlockSpec } from '@blocksuite/affine-block-surface';
|
||||
|
||||
import { EdgelessTextBlockSpec } from '../../edgeless-text-block/index.js';
|
||||
import { EdgelessRootBlockSpec } from '../../root-block/edgeless/edgeless-root-spec.js';
|
||||
import { EdgelessSurfaceRefBlockSpec } from '../../surface-ref-block/surface-ref-spec.js';
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { EdgelessTextBlockSpec } from '@blocksuite/affine-block-edgeless-text';
|
||||
import { FrameBlockSpec } from '@blocksuite/affine-block-frame';
|
||||
import { LatexBlockSpec } from '@blocksuite/affine-block-latex';
|
||||
import {
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
import { FontLoaderService } from '@blocksuite/affine-shared/services';
|
||||
import type { ExtensionType } from '@blocksuite/block-std';
|
||||
|
||||
import { EdgelessTextBlockSpec } from '../../edgeless-text-block/edgeless-text-spec.js';
|
||||
import { EdgelessRootBlockSpec } from '../../root-block/edgeless/edgeless-root-spec.js';
|
||||
import {
|
||||
EdgelessFrameManager,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { EdgelessTextBlockSpec } from '@blocksuite/affine-block-edgeless-text';
|
||||
import { FrameBlockSpec } from '@blocksuite/affine-block-frame';
|
||||
import { LatexBlockSpec } from '@blocksuite/affine-block-latex';
|
||||
import {
|
||||
@@ -19,7 +20,6 @@ import {
|
||||
} from '@blocksuite/block-std';
|
||||
import { literal } from 'lit/static-html.js';
|
||||
|
||||
import { EdgelessTextBlockSpec } from '../../edgeless-text-block/index.js';
|
||||
import { PreviewEdgelessRootBlockSpec } from '../../root-block/edgeless/edgeless-root-spec.js';
|
||||
import { PageRootService } from '../../root-block/page/page-root-service.js';
|
||||
import {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import type { BlockCommands } from '@blocksuite/block-std';
|
||||
|
||||
import { insertEdgelessTextCommand } from './insert-edgeless-text.js';
|
||||
|
||||
export const commands: BlockCommands = {
|
||||
insertEdgelessText: insertEdgelessTextCommand,
|
||||
};
|
||||
@@ -1,111 +0,0 @@
|
||||
import {
|
||||
EdgelessCRUDIdentifier,
|
||||
getSurfaceBlock,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
|
||||
import type { Command } from '@blocksuite/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||
import { Bound } from '@blocksuite/global/utils';
|
||||
|
||||
import {
|
||||
EDGELESS_TEXT_BLOCK_MIN_HEIGHT,
|
||||
EDGELESS_TEXT_BLOCK_MIN_WIDTH,
|
||||
EdgelessTextBlockComponent,
|
||||
} from '../edgeless-text-block.js';
|
||||
|
||||
export const insertEdgelessTextCommand: Command<
|
||||
never,
|
||||
'textId',
|
||||
{
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
> = (ctx, next) => {
|
||||
const { std, x, y } = ctx;
|
||||
const host = std.host;
|
||||
const doc = host.doc;
|
||||
const surface = getSurfaceBlock(doc);
|
||||
if (!surface) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
const gfx = std.get(GfxControllerIdentifier);
|
||||
const zoom = gfx.viewport.zoom;
|
||||
const selection = gfx.selection;
|
||||
|
||||
const textId = std.get(EdgelessCRUDIdentifier).addBlock(
|
||||
'affine:edgeless-text',
|
||||
{
|
||||
xywh: new Bound(
|
||||
x - (EDGELESS_TEXT_BLOCK_MIN_WIDTH * zoom) / 2,
|
||||
y - (EDGELESS_TEXT_BLOCK_MIN_HEIGHT * zoom) / 2,
|
||||
EDGELESS_TEXT_BLOCK_MIN_WIDTH * zoom,
|
||||
EDGELESS_TEXT_BLOCK_MIN_HEIGHT * zoom
|
||||
).serialize(),
|
||||
},
|
||||
surface.id
|
||||
);
|
||||
|
||||
const blockId = doc.addBlock('affine:paragraph', { type: 'text' }, textId);
|
||||
host.updateComplete
|
||||
.then(() => {
|
||||
selection.set({
|
||||
elements: [textId],
|
||||
editing: true,
|
||||
});
|
||||
const disposable = selection.slots.updated.on(() => {
|
||||
const editing = selection.editing;
|
||||
const id = selection.selectedIds[0];
|
||||
if (!editing || id !== textId) {
|
||||
const textBlock = host.view.getBlock(textId);
|
||||
if (textBlock instanceof EdgelessTextBlockComponent) {
|
||||
textBlock.model.hasMaxWidth = true;
|
||||
}
|
||||
|
||||
disposable.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
focusTextModel(std, blockId);
|
||||
host.updateComplete
|
||||
.then(() => {
|
||||
const edgelessText = host.view.getBlock(textId);
|
||||
const paragraph = host.view.getBlock(blockId);
|
||||
if (!edgelessText || !paragraph) return;
|
||||
|
||||
const abortController = new AbortController();
|
||||
edgelessText.addEventListener(
|
||||
'focusout',
|
||||
e => {
|
||||
if (edgelessText.model.children.length > 1) return;
|
||||
if (
|
||||
!paragraph.model.text ||
|
||||
(paragraph.model.text.length === 0 && e.relatedTarget !== null)
|
||||
) {
|
||||
doc.deleteBlock(edgelessText.model);
|
||||
}
|
||||
},
|
||||
{
|
||||
once: true,
|
||||
signal: abortController.signal,
|
||||
}
|
||||
);
|
||||
paragraph.model.deleted.once(() => {
|
||||
abortController.abort();
|
||||
});
|
||||
edgelessText.addEventListener(
|
||||
'beforeinput',
|
||||
() => {
|
||||
abortController.abort();
|
||||
},
|
||||
{
|
||||
once: true,
|
||||
}
|
||||
);
|
||||
})
|
||||
.catch(console.error);
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
next({ textId });
|
||||
};
|
||||
@@ -1,347 +0,0 @@
|
||||
import { TextUtils } from '@blocksuite/affine-block-surface';
|
||||
import type { EdgelessTextBlockModel } from '@blocksuite/affine-model';
|
||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||
import type { BlockComponent } from '@blocksuite/block-std';
|
||||
import { GfxBlockComponent } from '@blocksuite/block-std';
|
||||
import { Bound } from '@blocksuite/global/utils';
|
||||
import { css, html } from 'lit';
|
||||
import { query, state } from 'lit/decorators.js';
|
||||
import { type StyleInfo, styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import type { EdgelessRootService } from '../root-block/index.js';
|
||||
|
||||
export const EDGELESS_TEXT_BLOCK_MIN_WIDTH = 50;
|
||||
export const EDGELESS_TEXT_BLOCK_MIN_HEIGHT = 50;
|
||||
|
||||
export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBlockModel> {
|
||||
static override styles = css`
|
||||
.edgeless-text-block-container[data-max-width='false'] .inline-editor span {
|
||||
word-break: keep-all !important;
|
||||
text-wrap: nowrap !important;
|
||||
}
|
||||
|
||||
.edgeless-text-block-container affine-paragraph,
|
||||
affine-list {
|
||||
color: var(--edgeless-text-color);
|
||||
font-family: var(--edgeless-text-font-family);
|
||||
font-style: var(--edgeless-text-font-style);
|
||||
font-weight: var(--edgeless-text-font-weight);
|
||||
text-align: var(--edgeless-text-text-align);
|
||||
}
|
||||
`;
|
||||
|
||||
private readonly _resizeObserver = new ResizeObserver(() => {
|
||||
if (this.doc.readonly) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.model.hasMaxWidth) {
|
||||
this._updateW();
|
||||
}
|
||||
|
||||
this._updateH();
|
||||
});
|
||||
|
||||
get rootService() {
|
||||
return this.std.getService('affine:page') as EdgelessRootService;
|
||||
}
|
||||
|
||||
private _updateH() {
|
||||
const bound = Bound.deserialize(this.model.xywh);
|
||||
const rect = this._textContainer.getBoundingClientRect();
|
||||
bound.h = rect.height / this.gfx.viewport.zoom;
|
||||
|
||||
this.doc.updateBlock(this.model, {
|
||||
xywh: bound.serialize(),
|
||||
});
|
||||
}
|
||||
|
||||
private _updateW() {
|
||||
const bound = Bound.deserialize(this.model.xywh);
|
||||
const rect = this._textContainer.getBoundingClientRect();
|
||||
bound.w = Math.max(
|
||||
rect.width / this.gfx.viewport.zoom,
|
||||
EDGELESS_TEXT_BLOCK_MIN_WIDTH * this.gfx.viewport.zoom
|
||||
);
|
||||
|
||||
this.doc.updateBlock(this.model, {
|
||||
xywh: bound.serialize(),
|
||||
});
|
||||
}
|
||||
|
||||
checkWidthOverflow(width: number) {
|
||||
let wValid = true;
|
||||
|
||||
const oldWidthStr = this._textContainer.style.width;
|
||||
this._textContainer.style.width = `${width}px`;
|
||||
if (
|
||||
this.childrenContainer.scrollWidth > this.childrenContainer.offsetWidth
|
||||
) {
|
||||
wValid = false;
|
||||
}
|
||||
this._textContainer.style.width = oldWidthStr;
|
||||
|
||||
return wValid;
|
||||
}
|
||||
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
this.disposables.add(
|
||||
this.model.propsUpdated.on(({ key }) => {
|
||||
this.updateComplete
|
||||
.then(() => {
|
||||
if (!this.host) return;
|
||||
|
||||
const command = this.host.command;
|
||||
const blockSelections = this.model.children.map(child =>
|
||||
this.host.selection.create('block', {
|
||||
blockId: child.id,
|
||||
})
|
||||
);
|
||||
|
||||
if (key === 'fontStyle') {
|
||||
command.exec('formatBlock', {
|
||||
blockSelections,
|
||||
styles: {
|
||||
italic: null,
|
||||
},
|
||||
});
|
||||
} else if (key === 'color') {
|
||||
command.exec('formatBlock', {
|
||||
blockSelections,
|
||||
styles: {
|
||||
color: null,
|
||||
},
|
||||
});
|
||||
} else if (key === 'fontWeight') {
|
||||
command.exec('formatBlock', {
|
||||
blockSelections,
|
||||
styles: {
|
||||
bold: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
override firstUpdated(props: Map<string, unknown>) {
|
||||
super.firstUpdated(props);
|
||||
|
||||
const { disposables, rootService } = this;
|
||||
const edgelessSelection = rootService.selection;
|
||||
|
||||
disposables.add(
|
||||
edgelessSelection.slots.updated.on(() => {
|
||||
if (edgelessSelection.has(this.model.id) && edgelessSelection.editing) {
|
||||
this._editing = true;
|
||||
} else {
|
||||
this._editing = false;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this._resizeObserver.observe(this._textContainer);
|
||||
disposables.add(() => {
|
||||
this._resizeObserver.disconnect();
|
||||
});
|
||||
|
||||
disposables.addFromEvent(this._textContainer, 'click', e => {
|
||||
if (!this._editing) return;
|
||||
|
||||
const containerRect = this._textContainer.getBoundingClientRect();
|
||||
const isTop = e.clientY < containerRect.top + containerRect.height / 2;
|
||||
|
||||
let newParagraphId: string | null = null;
|
||||
if (isTop) {
|
||||
const firstChild = this.model.firstChild();
|
||||
if (
|
||||
!firstChild ||
|
||||
!matchFlavours(firstChild, ['affine:list', 'affine:paragraph'])
|
||||
) {
|
||||
newParagraphId = this.doc.addBlock(
|
||||
'affine:paragraph',
|
||||
{},
|
||||
this.model.id,
|
||||
0
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const lastChild = this.model.lastChild();
|
||||
if (
|
||||
!lastChild ||
|
||||
!matchFlavours(lastChild, ['affine:list', 'affine:paragraph'])
|
||||
) {
|
||||
newParagraphId = this.doc.addBlock(
|
||||
'affine:paragraph',
|
||||
{},
|
||||
this.model.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (newParagraphId) {
|
||||
this.rootService.selectionManager.setGroup('note', [
|
||||
this.rootService.selectionManager.create('text', {
|
||||
from: {
|
||||
blockId: newParagraphId,
|
||||
index: 0,
|
||||
length: 0,
|
||||
},
|
||||
to: null,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
disposables.addFromEvent(this._textContainer, 'focusout', () => {
|
||||
if (!this._editing) return;
|
||||
|
||||
this.rootService.selectionManager.clear();
|
||||
});
|
||||
|
||||
let composingWidth = EDGELESS_TEXT_BLOCK_MIN_WIDTH;
|
||||
disposables.addFromEvent(this, 'compositionupdate', () => {
|
||||
composingWidth = Math.max(
|
||||
this._textContainer.offsetWidth,
|
||||
EDGELESS_TEXT_BLOCK_MIN_HEIGHT
|
||||
);
|
||||
});
|
||||
disposables.addFromEvent(this, 'compositionend', () => {
|
||||
if (this.model.hasMaxWidth) {
|
||||
composingWidth = EDGELESS_TEXT_BLOCK_MIN_WIDTH;
|
||||
return;
|
||||
}
|
||||
// when IME finish container will crash to a small width, so
|
||||
// we set a max width to prevent this
|
||||
this._textContainer.style.width = `${composingWidth}px`;
|
||||
this.model.hasMaxWidth = true;
|
||||
requestAnimationFrame(() => {
|
||||
this._textContainer.style.width = '';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
override getCSSTransform(): string {
|
||||
const viewport = this.gfx.viewport;
|
||||
const { translateX, translateY, zoom } = viewport;
|
||||
const bound = Bound.deserialize(this.model.xywh);
|
||||
|
||||
const scaledX = bound.x * zoom;
|
||||
const scaledY = bound.y * zoom;
|
||||
const deltaX = scaledX - bound.x;
|
||||
const deltaY = scaledY - bound.y;
|
||||
|
||||
return `translate(${translateX + deltaX}px, ${translateY + deltaY}px) scale(${zoom * this.model.scale})`;
|
||||
}
|
||||
|
||||
override getRenderingRect() {
|
||||
const { xywh, scale, rotate, hasMaxWidth } = this.model;
|
||||
const bound = Bound.deserialize(xywh);
|
||||
const w = hasMaxWidth ? bound.w / scale : undefined;
|
||||
|
||||
return {
|
||||
x: bound.x,
|
||||
y: bound.y,
|
||||
w,
|
||||
h: bound.h / scale,
|
||||
rotate,
|
||||
zIndex: this.toZIndex(),
|
||||
};
|
||||
}
|
||||
|
||||
override renderGfxBlock() {
|
||||
const { model } = this;
|
||||
const { rotate, hasMaxWidth } = model;
|
||||
const editing = this._editing;
|
||||
const containerStyle: StyleInfo = {
|
||||
transform: `rotate(${rotate}deg)`,
|
||||
transformOrigin: 'center',
|
||||
border: `1px solid ${editing ? 'var(--affine—primary—color, #1e96eb)' : 'transparent'}`,
|
||||
borderRadius: '4px',
|
||||
boxSizing: 'border-box',
|
||||
boxShadow: editing ? '0px 0px 0px 2px rgba(30, 150, 235, 0.3)' : 'none',
|
||||
fontWeight: '400',
|
||||
lineHeight: 'var(--affine-line-height)',
|
||||
};
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="edgeless-text-block-container"
|
||||
data-max-width="${hasMaxWidth}"
|
||||
style=${styleMap(containerStyle)}
|
||||
>
|
||||
<div
|
||||
style=${styleMap({
|
||||
pointerEvents: editing ? 'auto' : 'none',
|
||||
userSelect: editing ? 'auto' : 'none',
|
||||
})}
|
||||
contenteditable=${editing}
|
||||
>
|
||||
${this.renderPageContent()}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
override renderPageContent() {
|
||||
const { fontFamily, fontStyle, fontWeight, textAlign } = this.model;
|
||||
const color = this.std
|
||||
.get(ThemeProvider)
|
||||
.generateColorProperty(this.model.color, '#000000');
|
||||
|
||||
const style = styleMap({
|
||||
'--edgeless-text-color': color,
|
||||
'--edgeless-text-font-family': TextUtils.wrapFontFamily(fontFamily),
|
||||
'--edgeless-text-font-style': fontStyle,
|
||||
'--edgeless-text-font-weight': fontWeight,
|
||||
'--edgeless-text-text-align': textAlign,
|
||||
'--affine-list-margin': '0',
|
||||
'--affine-paragraph-margin': '0',
|
||||
});
|
||||
|
||||
return html`
|
||||
<div style=${style} class="affine-block-children-container">
|
||||
${this.renderChildren(this.model)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
tryFocusEnd() {
|
||||
const paragraphOrLists = Array.from(
|
||||
this.querySelectorAll<BlockComponent>('affine-paragraph, affine-list')
|
||||
);
|
||||
const last = paragraphOrLists.at(-1);
|
||||
if (last) {
|
||||
this.host.selection.setGroup('note', [
|
||||
this.host.selection.create('text', {
|
||||
from: {
|
||||
blockId: last.blockId,
|
||||
index: last.model.text?.length ?? 0,
|
||||
length: 0,
|
||||
},
|
||||
to: null,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@state()
|
||||
private accessor _editing = false;
|
||||
|
||||
@query('.edgeless-text-block-container')
|
||||
private accessor _textContainer!: HTMLDivElement;
|
||||
|
||||
@query('.affine-block-children-container')
|
||||
accessor childrenContainer!: HTMLDivElement;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'affine-edgeless-text': EdgelessTextBlockComponent;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import {
|
||||
BlockViewExtension,
|
||||
CommandExtension,
|
||||
type ExtensionType,
|
||||
} from '@blocksuite/block-std';
|
||||
import { literal } from 'lit/static-html.js';
|
||||
|
||||
import { commands } from './commands/index.js';
|
||||
|
||||
export const EdgelessTextBlockSpec: ExtensionType[] = [
|
||||
CommandExtension(commands),
|
||||
BlockViewExtension('affine:edgeless-text', literal`affine-edgeless-text`),
|
||||
];
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './edgeless-text-block.js';
|
||||
export * from './edgeless-text-spec.js';
|
||||
@@ -1,5 +1,6 @@
|
||||
import { effects as blockAttachmentEffects } from '@blocksuite/affine-block-attachment/effects';
|
||||
import { effects as blockBookmarkEffects } from '@blocksuite/affine-block-bookmark/effects';
|
||||
import { effects as blockEdgelessTextEffects } from '@blocksuite/affine-block-edgeless-text/effects';
|
||||
import { effects as blockEmbedEffects } from '@blocksuite/affine-block-embed/effects';
|
||||
import { effects as blockFrameEffects } from '@blocksuite/affine-block-frame/effects';
|
||||
import { effects as blockImageEffects } from '@blocksuite/affine-block-image/effects';
|
||||
@@ -64,8 +65,6 @@ import {
|
||||
HeaderAreaTextCellEditing,
|
||||
} from './database-block/properties/title/text.js';
|
||||
import { DividerBlockComponent } from './divider-block/index.js';
|
||||
import type { insertEdgelessTextCommand } from './edgeless-text-block/commands/insert-edgeless-text.js';
|
||||
import { EdgelessTextBlockComponent } from './edgeless-text-block/index.js';
|
||||
import { EdgelessAutoCompletePanel } from './root-block/edgeless/components/auto-complete/auto-complete-panel.js';
|
||||
import { EdgelessAutoComplete } from './root-block/edgeless/components/auto-complete/edgeless-auto-complete.js';
|
||||
import { EdgelessToolIconButton } from './root-block/edgeless/components/buttons/tool-icon-button.js';
|
||||
@@ -260,6 +259,7 @@ export function effects() {
|
||||
blockDatabaseEffects();
|
||||
blockSurfaceRefEffects();
|
||||
blockLatexEffects();
|
||||
blockEdgelessTextEffects();
|
||||
|
||||
componentCaptionEffects();
|
||||
componentContextMenuEffects();
|
||||
@@ -293,7 +293,6 @@ export function effects() {
|
||||
'affine-database-rich-text-cell-editing',
|
||||
RichTextCellEditing
|
||||
);
|
||||
customElements.define('affine-edgeless-text', EdgelessTextBlockComponent);
|
||||
customElements.define('center-peek', CenterPeek);
|
||||
customElements.define('database-datasource-note-renderer', NoteRenderer);
|
||||
customElements.define('database-datasource-block-renderer', BlockRenderer);
|
||||
@@ -528,14 +527,10 @@ export function effects() {
|
||||
|
||||
declare global {
|
||||
namespace BlockSuite {
|
||||
interface Commands {
|
||||
insertEdgelessText: typeof insertEdgelessTextCommand;
|
||||
}
|
||||
interface CommandContext {
|
||||
focusBlock?: BlockComponent | null;
|
||||
anchorBlock?: BlockComponent | null;
|
||||
updatedBlocks?: BlockModel[];
|
||||
textId?: string;
|
||||
}
|
||||
interface BlockConfigs {
|
||||
'affine:code': CodeBlockConfig;
|
||||
|
||||
@@ -20,7 +20,6 @@ export * from './code-block/index.js';
|
||||
export * from './data-view-block/index.js';
|
||||
export * from './database-block/index.js';
|
||||
export * from './divider-block/index.js';
|
||||
export * from './edgeless-text-block/index.js';
|
||||
export { EdgelessTemplatePanel } from './root-block/edgeless/components/toolbar/template/template-panel.js';
|
||||
export type {
|
||||
Template,
|
||||
@@ -46,6 +45,7 @@ export {
|
||||
export * from './surface-ref-block/index.js';
|
||||
export * from '@blocksuite/affine-block-attachment';
|
||||
export * from '@blocksuite/affine-block-bookmark';
|
||||
export * from '@blocksuite/affine-block-edgeless-text';
|
||||
export * from '@blocksuite/affine-block-embed';
|
||||
export * from '@blocksuite/affine-block-frame';
|
||||
export * from '@blocksuite/affine-block-image';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { EdgelessTextBlockComponent } from '@blocksuite/affine-block-edgeless-text';
|
||||
import { EDGELESS_TEXT_BLOCK_MIN_WIDTH } from '@blocksuite/affine-block-edgeless-text';
|
||||
import {
|
||||
EMBED_HTML_MIN_HEIGHT,
|
||||
EMBED_HTML_MIN_WIDTH,
|
||||
@@ -59,8 +61,6 @@ import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import { isMindmapNode } from '../../../../_common/edgeless/mindmap/index.js';
|
||||
import type { EdgelessTextBlockComponent } from '../../../../edgeless-text-block/edgeless-text-block.js';
|
||||
import { EDGELESS_TEXT_BLOCK_MIN_WIDTH } from '../../../../edgeless-text-block/edgeless-text-block.js';
|
||||
import type { EdgelessRootBlockComponent } from '../../edgeless-root-block.js';
|
||||
import type {
|
||||
EdgelessFrameManager,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { EdgelessTextBlockComponent } from '@blocksuite/affine-block-edgeless-text';
|
||||
import {
|
||||
ConnectorElementModel,
|
||||
ConnectorMode,
|
||||
@@ -27,7 +28,6 @@ import {
|
||||
isSingleMindMapNode,
|
||||
} from '../../_common/edgeless/mindmap/index.js';
|
||||
import { LassoMode } from '../../_common/types.js';
|
||||
import { EdgelessTextBlockComponent } from '../../edgeless-text-block/edgeless-text-block.js';
|
||||
import { PageKeyboardManager } from '../keyboard/keyboard-manager.js';
|
||||
import { GfxBlockModel } from './block-model.js';
|
||||
import type { EdgelessRootBlockComponent } from './edgeless-root-block.js';
|
||||
|
||||
Reference in New Issue
Block a user