Skip to content

BlockSuite API Documentation / @blocksuite/affine-gfx-text

@blocksuite/affine-gfx-text

Classes

Extension

TextTool

Understanding Extensions

Extensions provide a way to extend the functionality of a system using dependency injection. They allow you to register services, implementations, and factories in the DI container, which can then be retrieved and used by different parts of the application.

Extensions are particularly useful for:

  • Registering different implementations for different types
  • Creating pluggable architecture where components can be added or removed
  • Managing dependencies between different parts of the application

Usage Example: Fruit Processing System

Let's consider a fruit processing system where different types of fruits need different processing methods. We'll show how to implement this using extensions.

Step 1: Define the interfaces

ts
interface FruitProcessor {
  process(fruit: Fruit): void;
}

interface Fruit {
  type: string;
  // other properties
}

Step 2: Create a service identifier

ts
import { createIdentifier } from '@blocksuite/global/di';

const FruitProcessorProvider = createIdentifier<FruitProcessor>('fruit-processor-provider');

Step 3: Create implementations

ts
class AppleProcessor implements FruitProcessor {
  process(fruit: Fruit): void {
    console.log('Slicing apple');
    // Apple-specific processing
  }
}

class BananaProcessor implements FruitProcessor {
  process(fruit: Fruit): void {
    console.log('Peeling banana');
    // Banana-specific processing
  }
}

Step 4: Create an extension factory

ts
const FruitProcessorExtension = (
  fruitType: string,
  implementation: new () => FruitProcessor
): ExtensionType => {
  return {
    setup: di => {
      di.addImpl(FruitProcessorProvider(fruitType), implementation);
    }
  };
};

Step 5: Create concrete extensions

ts
export const AppleProcessorExtension = FruitProcessorExtension('apple', AppleProcessor);
export const BananaProcessorExtension = FruitProcessorExtension('banana', BananaProcessor);

Step 6: Use the extensions

ts
import { Container } from '@blocksuite/global/di';

class FruitProcessingSystem {
  provider: ServiceProvider;

  constructor(extensions: ExtensionType[]) {
    const container = new Container();

    // Set up all extensions
    extensions.forEach(ext => ext.setup(container));

    // Create a provider from the container
    this.provider = container.provider();
  }

  processFruit(fruit: Fruit) {
    // Get the appropriate processor based on fruit type
    const processor = this.provider.get(FruitProcessorProvider(fruit.type));

    // Process the fruit
    processor.process(fruit);
  }
}

// Initialize the system with extensions
const system = new FruitProcessingSystem([
  AppleProcessorExtension,
  BananaProcessorExtension
]);

// Use the system
system.processFruit({ type: 'apple' });  // Output: Slicing apple
system.processFruit({ type: 'banana' }); // Output: Peeling banana

Note: We deliberately used a non-block specific example here. In BlockSuite, the extension pattern can be applied to any entity that can be configured by third parties, not just blocks. This includes different tools in the whiteboard, different column types in database blocks, and many other extensible components. The pattern remains the same regardless of what you're extending.

Extends
Constructors
Properties
toolName

static toolName: string = 'text'

Overrides

BaseTool.toolName

Accessors
Methods
click()

click(e): void

Parameters
e

PointerEventState

Returns

void

Overrides

BaseTool.click

Other

EdgelessTextEditor

Extends
Constructors
Other
BORDER_WIDTH

static BORDER_WIDTH: number = 1

PADDING_HORIZONTAL

static PADDING_HORIZONTAL: number = 10

PADDING_VERTICAL

static PADDING_VERTICAL: number = 6

PLACEHOLDER_TEXT

static PLACEHOLDER_TEXT: string = 'Type from here'

styles

static styles: CSSResult

Overrides

WithDisposable(ShadowlessElement).styles

crud
Get Signature

get crud(): EdgelessCRUDExtension

Returns

EdgelessCRUDExtension

element
gfx
Get Signature

get gfx(): GfxController

Returns

GfxController

inlineEditor
Get Signature

get inlineEditor(): AffineInlineEditor | null

Returns

AffineInlineEditor | null

inlineEditorContainer
Get Signature

get inlineEditorContainer(): InlineRootElement<AffineTextAttributes> | null | undefined

Returns

InlineRootElement<AffineTextAttributes> | null | undefined

richText
std
connectedCallback()

connectedCallback(): void

Returns

void

Overrides

WithDisposable(ShadowlessElement).connectedCallback

getContainerOffset()

getContainerOffset(): string

Returns

string

getCoordsOnCenterAlign()

getCoordsOnCenterAlign(rect, w1, h1): object

Parameters
rect
h

number

r

number

w

number

x

number

y

number

w1

number

h1

number

Returns

object

x

x: number

y

y: number

getCoordsOnLeftAlign()

getCoordsOnLeftAlign(rect, w1, h1): object

Parameters
rect
h

number

r

number

w

number

x

number

y

number

w1

number

h1

number

Returns

object

x

x: number

y

y: number

getCoordsOnRightAlign()

getCoordsOnRightAlign(rect, w1, h1): object

Parameters
rect
h

number

r

number

w

number

x

number

y

number

w1

number

h1

number

Returns

object

x

x: number

y

y: number

getVisualPosition()

getVisualPosition(element): IVec

Parameters
element

TextElementModel

Returns

IVec

setKeeping()

setKeeping(keeping): void

Parameters
keeping

boolean

Returns

void

attributes
controllers
dev-mode
lifecycle
properties
rendering
render()

render(): TemplateResult<1>

Invoked on each update to perform rendering tasks. This method may return any value renderable by lit-html's ChildPart - typically a TemplateResult. Setting properties inside this method will not trigger the element to update.

Returns

TemplateResult<1>

Overrides

WithDisposable(ShadowlessElement).render

styles
updates
firstUpdated()

firstUpdated(): void

Invoked when the element is first updated. Implement to perform one time work on the element after update.

ts
firstUpdated() {
  this.renderRoot.getElementById('my-text-area').focus();
}

Setting properties inside this method will trigger the element to update again after this update cycle completes.

Returns

void

Overrides

WithDisposable(ShadowlessElement).firstUpdated

getUpdateComplete()

getUpdateComplete(): Promise<boolean>

Override point for the updateComplete promise.

It is not safe to override the updateComplete getter directly due to a limitation in TypeScript which means it is not possible to call a superclass getter (e.g. super.updateComplete.then(...)) when the target language is ES5 (https://github.com/microsoft/TypeScript/issues/338). This method should be overridden instead. For example:

ts
class MyElement extends LitElement {
  override async getUpdateComplete() {
    const result = await super.getUpdateComplete();
    await this._myChild.updateComplete;
    return result;
  }
}
Returns

Promise<boolean>

A promise of a boolean that resolves to true if the update completed without triggering another update.

Overrides

WithDisposable(ShadowlessElement).getUpdateComplete


TextElementView

The methods that a graphic element should implement. It is already included in the GfxCompatibleInterface interface.

Extends
Constructors
Properties
type

static type: string = 'text'

Overrides

GfxElementModelView.type

Accessors
Methods
onCreated()

onCreated(): void

Returns

void

Overrides

GfxElementModelView.onCreated

Type Aliases

TextDelta

TextDelta = object

Properties

attributes?

optional attributes: Record<string, unknown>

insert

insert: string

Variables

charWidth

const charWidth: object

Type Declaration

calculate()

calculate: (char, font) => number

Parameters
char

string

font

string

Returns

number

getCache()

getCache: (font) => number[] | undefined

Parameters
font

string

Returns

number[] | undefined


insertEdgelessTextCommand

const insertEdgelessTextCommand: Command<{ x: number; y: number; }, { textId: string; }>


text

const text: ElementRenderer<TextElementModel>


TextElementRendererExtension

const TextElementRendererExtension: ExtensionType & object

Type Declaration

identifier

identifier: ServiceIdentifier<ElementRenderer<TextElementModel>>


TextInteraction

const TextInteraction: ExtensionType


textToMarkdownAdapterMatcher

const textToMarkdownAdapterMatcher: ExtensionType & object

Type Declaration

identifier

identifier: ServiceIdentifier<ElementToMarkdownAdapterMatcher>


textToolbarConfig

const textToolbarConfig: object

Type Declaration

actions

readonly actions: [{ id: "a.font"; content: TemplateResult<1> | null; }, { id: "b.text-color"; content: TemplateResult<1> | null; }, { id: "c.font-style"; content: TemplateResult<1> | null; }, { id: "d.font-size"; when: boolean; content: TemplateResult<1> | null; }, { id: "e.alignment"; content: TemplateResult<1> | null; }]

when()

readonly when: (ctx) => boolean

Parameters
ctx

ToolbarContext

Returns

boolean


textToolbarExtension

const textToolbarExtension: ExtensionType


textToPlainTextAdapterMatcher

const textToPlainTextAdapterMatcher: ExtensionType & object

Type Declaration

identifier

identifier: ServiceIdentifier<ElementToPlainTextAdapterMatcher>

Functions

addText()

addText(edgeless, event): void

Parameters

edgeless

BlockComponent

event

PointerEventState

Returns

void

Deprecated

Canvas Text has been deprecated


createTextActions()

createTextActions<K, T>(klass, type, update, mapInto, stash): [{ id: "a.font"; content: TemplateResult<1> | null; }, { id: "b.text-color"; content: TemplateResult<1> | null; }, { id: "c.font-style"; content: TemplateResult<1> | null; }, { id: "d.font-size"; when: boolean; content: TemplateResult<1> | null; }, { id: "e.alignment"; content: TemplateResult<1> | null; }]

Type Parameters

K

K extends (...args) => any

T

T extends keyof SurfaceTextModelMap

Parameters

klass

K

type

T

update

(ctx, model, props) => void

mapInto

(model) => TextStyleProps

stash

<P>(model, type, field) => void

Returns

[{ id: "a.font"; content: TemplateResult<1> | null; }, { id: "b.text-color"; content: TemplateResult<1> | null; }, { id: "c.font-style"; content: TemplateResult<1> | null; }, { id: "d.font-size"; when: boolean; content: TemplateResult<1> | null; }, { id: "e.alignment"; content: TemplateResult<1> | null; }]


getCursorByCoord()

getCursorByCoord(model, coord): number

Parameters

model

TextElementModel

coord
x

number

y

number

Returns

number


getFontMetrics()

getFontMetrics(fontFamily, fontSize, fontWeight): TextMetrics

Parameters

fontFamily

string

fontSize

number

fontWeight

string

Returns

TextMetrics


getFontString()

getFontString(__namedParameters): string

Parameters

__namedParameters
fontFamily

string

fontSize

number

fontStyle

string

fontWeight

string

Returns

string


getLineHeight()

getLineHeight(fontFamily, fontSize, fontWeight): number

Parameters

fontFamily

string

fontSize

number

fontWeight

string

Returns

number


getLineWidth()

getLineWidth(text, font): number

Parameters

text

string

font

string

Returns

number


getTextCursorPosition()

getTextCursorPosition(model, coord): number[]

Parameters

model

TextElementModel

coord
x

number

y

number

Returns

number[]


getTextHeight()

getTextHeight(text, lineHeight): number

Parameters

text

string

lineHeight

number

Returns

number


getTextWidth()

getTextWidth(text, font): number

Parameters

text

string

font

string

Returns

number


isFontStyleSupported()

isFontStyleSupported(fontFamily, style): boolean

Parameters

fontFamily

string

style

FontStyle

Returns

boolean


isFontWeightSupported()

isFontWeightSupported(fontFamily, weight): boolean

Parameters

fontFamily

string

weight

FontWeight

Returns

boolean


isRTL()

isRTL(text): boolean

Parameters

text

string

Returns

boolean


measureTextInDOM()

measureTextInDOM(fontFamily, fontSize, fontWeight): object

Parameters

fontFamily

string

fontSize

number

fontWeight

string

Returns

object

lineGap

lineGap: number

lineHeight

lineHeight: number


mountTextElementEditor()

mountTextElementEditor(textElement, edgeless, focusCoord?): void

Parameters

textElement

TextElementModel

edgeless

BlockComponent

focusCoord?

IModelCoord

Returns

void


normalizeText()

normalizeText(text): string

Parameters

text

string

Returns

string


normalizeTextBound()

normalizeTextBound(__namedParameters, bound, dragging): Bound

Parameters

__namedParameters
fontFamily

FontFamily

fontSize

number

fontStyle

FontStyle

fontWeight

FontWeight

hasMaxWidth?

boolean

maxWidth?

number

yText

YText

bound

Bound

dragging

boolean = false

Returns

Bound


parseTokens()

parseTokens(text): string[]

Parameters

text

string

Returns

string[]


splitIntoLines()

splitIntoLines(text): string[]

Parameters

text

string

Returns

string[]


truncateTextByWidth()

truncateTextByWidth(text, font, width): string

Parameters

text

string

font

string

width

number

Returns

string


wrapText()

wrapText(text, font, maxWidth): string

Parameters

text

string

font

string

maxWidth

number

Returns

string


wrapTextDeltas()

wrapTextDeltas(text, font, w): TextDelta[]

Parameters

text

YText

font

string

w

number

Returns

TextDelta[]