import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { html, LitElement, type TemplateResult } from 'lit'; import { property } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; import { INLINE_ROOT_ATTR, ZERO_WIDTH_SPACE } from '../consts.js'; import type { InlineRootElement } from '../inline-editor.js'; import type { DeltaInsert } from '../types.js'; import { EmbedGap } from './embed-gap.js'; export class VLine extends LitElement { get inlineEditor() { const rootElement = this.closest( `[${INLINE_ROOT_ATTR}]` ) as InlineRootElement; if (!rootElement) { throw new BlockSuiteError( BlockSuiteError.ErrorCode.ValueNotExists, 'v-line must be inside a v-root' ); } const inlineEditor = rootElement.inlineEditor; if (!inlineEditor) { throw new BlockSuiteError( BlockSuiteError.ErrorCode.ValueNotExists, 'v-line must be inside a v-root with inline-editor' ); } return inlineEditor; } get vElements() { return Array.from(this.querySelectorAll('v-element')); } get vTextContent() { return this.vElements.reduce((acc, el) => acc + el.delta.insert, ''); } get vTextLength() { return this.vElements.reduce((acc, el) => acc + el.delta.insert.length, 0); } // you should use vElements.length or vTextLength because v-element corresponds to the actual delta get vTexts() { return Array.from(this.querySelectorAll('v-text')); } override createRenderRoot() { return this; } protected override firstUpdated(): void { this.style.display = 'block'; this.addEventListener('mousedown', e => { if (e.detail >= 2 && this.startOffset === this.endOffset) { e.preventDefault(); return; } if (e.detail >= 3) { e.preventDefault(); this.inlineEditor.setInlineRange({ index: this.startOffset, length: this.endOffset - this.startOffset, }); } }); } // vTexts.length > 0 does not mean the line is not empty, override async getUpdateComplete() { const result = await super.getUpdateComplete(); await Promise.all(this.vElements.map(el => el.updateComplete)); return result; } override render() { if (!this.isConnected) return; if (this.inlineEditor.vLineRenderer) { return this.inlineEditor.vLineRenderer(this); } return this.renderVElements(); } renderVElements() { if (this.elements.length === 0) { // don't use v-element because it not correspond to the actual delta return html`