refactor(editor): rename block-std to std (#11250)

Closes: BS-2946
This commit is contained in:
Saul-Mirone
2025-03-28 07:20:34 +00:00
parent 4498676a96
commit 205cd7a86d
1029 changed files with 1580 additions and 1698 deletions
@@ -0,0 +1,139 @@
import { DisposableGroup } from '@blocksuite/global/disposable';
import { onSurfaceAdded } from '../../utils/gfx.js';
import {
type GfxBlockComponent,
isGfxBlockComponent,
} from '../../view/index.js';
import type { GfxController } from '../controller.js';
import { GfxExtension, GfxExtensionIdentifier } from '../extension.js';
import type { GfxModel } from '../model/model.js';
import type { GfxPrimitiveElementModel } from '../model/surface/element-model.js';
import type { GfxLocalElementModel } from '../model/surface/local-element-model.js';
import type { SurfaceBlockModel } from '../model/surface/surface-model.js';
import {
GfxElementModelView,
GfxElementModelViewExtIdentifier,
} from './view.js';
export class ViewManager extends GfxExtension {
static override key = 'viewManager';
private readonly _disposable = new DisposableGroup();
private readonly _viewCtorMap = new Map<string, typeof GfxElementModelView>();
private readonly _viewMap = new Map<string, GfxElementModelView>();
constructor(gfx: GfxController) {
super(gfx);
}
static override extendGfx(gfx: GfxController): void {
Object.defineProperty(gfx, 'view', {
get() {
return this.std.get(GfxExtensionIdentifier('viewManager'));
},
});
}
get(
model: GfxModel | GfxLocalElementModel | string
): GfxElementModelView | GfxBlockComponent | null {
model = typeof model === 'string' ? model : model.id;
if (this._viewMap.has(model)) {
return this._viewMap.get(model)!;
}
const blockView = this.std.view.getBlock(model);
if (blockView && isGfxBlockComponent(blockView)) {
return blockView;
}
return null;
}
override mounted(): void {
this.std.provider
.getAll(GfxElementModelViewExtIdentifier)
.forEach(viewCtor => {
this._viewCtorMap.set(viewCtor.type, viewCtor);
});
const updateViewOnElementChange = (surface: SurfaceBlockModel) => {
const createView = (
model: GfxPrimitiveElementModel | GfxLocalElementModel
) => {
const ViewCtor =
this._viewCtorMap.get(model.type) ?? GfxElementModelView;
const view = new ViewCtor(model, this.gfx);
this._viewMap.set(model.id, view);
view.onCreated();
};
this._disposable.add(
surface.elementAdded.subscribe(payload => {
const model = surface.getElementById(payload.id)!;
createView(model);
})
);
this._disposable.add(
surface.elementRemoved.subscribe(elem => {
const view = this._viewMap.get(elem.id);
this._viewMap.delete(elem.id);
view?.onDestroyed();
})
);
this._disposable.add(
surface.localElementAdded.subscribe(model => {
createView(model);
})
);
this._disposable.add(
surface.localElementDeleted.subscribe(model => {
const view = this._viewMap.get(model.id);
this._viewMap.delete(model.id);
view?.onDestroyed();
})
);
surface.localElementModels.forEach(model => {
createView(model);
});
surface.elementModels.forEach(model => {
createView(model);
});
};
if (this.gfx.surface) {
updateViewOnElementChange(this.gfx.surface);
} else {
this._disposable.add(
onSurfaceAdded(this.std.store, surface => {
if (surface) {
updateViewOnElementChange(surface);
}
})
);
}
}
override unmounted(): void {
this._disposable.dispose();
this._viewMap.forEach(view => view.onDestroyed());
this._viewMap.clear();
}
}
declare module '../controller.js' {
interface GfxController {
readonly view: ViewManager;
}
}
@@ -0,0 +1,221 @@
import { type Container, createIdentifier } from '@blocksuite/global/di';
import { DisposableGroup } from '@blocksuite/global/disposable';
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
import type { Bound, IVec } from '@blocksuite/global/gfx';
import type { Extension } from '@blocksuite/store';
import type { PointerEventState } from '../../event/index.js';
import type { EditorHost } from '../../view/index.js';
import type {
DragEndContext,
DragMoveContext,
DragStartContext,
GfxViewTransformInterface,
SelectedContext,
} from '../element-transform/view-transform.js';
import type { GfxController } from '../index.js';
import type { GfxElementGeometry, PointTestOptions } from '../model/base.js';
import { GfxPrimitiveElementModel } from '../model/surface/element-model.js';
import type { GfxLocalElementModel } from '../model/surface/local-element-model.js';
export type EventsHandlerMap = {
click: PointerEventState;
dblclick: PointerEventState;
pointerdown: PointerEventState;
pointerenter: PointerEventState;
pointerleave: PointerEventState;
pointermove: PointerEventState;
pointerup: PointerEventState;
};
export type SupportedEvent = keyof EventsHandlerMap;
export const GfxElementModelViewExtIdentifier = createIdentifier<
typeof GfxElementModelView
>('GfxElementModelView');
export class GfxElementModelView<
T extends GfxLocalElementModel | GfxPrimitiveElementModel =
| GfxPrimitiveElementModel
| GfxLocalElementModel,
RendererContext = object,
>
implements GfxElementGeometry, Extension, GfxViewTransformInterface
{
static type: string;
private readonly _handlers = new Map<
keyof EventsHandlerMap,
((evt: any) => void)[]
>();
private _isConnected = true;
protected disposable = new DisposableGroup();
readonly model: T;
get isConnected() {
return this._isConnected;
}
get rotate() {
return this.model.rotate;
}
get surface() {
return this.model.surface;
}
get type() {
return this.model.type;
}
get std() {
return this.gfx.std;
}
constructor(
model: T,
readonly gfx: GfxController
) {
this.model = model;
}
static setup(di: Container): void {
if (!this.type) {
throw new BlockSuiteError(
ErrorCode.ValueNotExists,
'The GfxElementModelView should have a static `type` property.'
);
}
di.addImpl(GfxElementModelViewExtIdentifier(this.type), () => this);
}
containsBound(bounds: Bound): boolean {
return this.model.containsBound(bounds);
}
dispatch<K extends keyof EventsHandlerMap>(
event: K,
evt: EventsHandlerMap[K]
) {
this._handlers.get(event)?.forEach(callback => callback(evt));
}
getLineIntersections(start: IVec, end: IVec) {
return this.model.getLineIntersections(start, end);
}
getNearestPoint(point: IVec) {
return this.model.getNearestPoint(point);
}
getRelativePointLocation(relativePoint: IVec) {
return this.model.getRelativePointLocation(relativePoint);
}
includesPoint(
x: number,
y: number,
_: PointTestOptions,
__: EditorHost
): boolean {
return this.model.includesPoint(x, y, _, __);
}
intersectsBound(bound: Bound): boolean {
return (
this.containsBound(bound) ||
bound.points.some((point, i, points) =>
this.getLineIntersections(point, points[(i + 1) % points.length])
)
);
}
off<K extends keyof EventsHandlerMap>(
event: K,
callback: (evt: EventsHandlerMap[K]) => void
) {
if (!this._handlers.has(event)) {
return;
}
const callbacks = this._handlers.get(event)!;
const index = callbacks.indexOf(callback);
if (index !== -1) {
callbacks.splice(index, 1);
}
}
on<K extends keyof EventsHandlerMap>(
event: K,
callback: (evt: EventsHandlerMap[K]) => void
) {
if (!this._handlers.has(event)) {
this._handlers.set(event, []);
}
this._handlers.get(event)!.push(callback);
return () => this.off(event, callback);
}
once<K extends keyof EventsHandlerMap>(
event: K,
callback: (evt: EventsHandlerMap[K]) => void
) {
const off = this.on(event, evt => {
off();
callback(evt);
});
return off;
}
onCreated() {}
onDragStart(_: DragStartContext) {
if (this.model instanceof GfxPrimitiveElementModel) {
this.model.stash('xywh');
}
}
onDragEnd(_: DragEndContext) {
if (this.model instanceof GfxPrimitiveElementModel) {
this.model.pop('xywh');
}
}
onDragMove({ dx, dy, currentBound }: DragMoveContext) {
this.model.xywh = currentBound.moveDelta(dx, dy).serialize();
}
onSelected(context: SelectedContext) {
if (this.model instanceof GfxPrimitiveElementModel) {
if (context.multiSelect) {
this.gfx.selection.toggle(this.model);
} else {
this.gfx.selection.set({ elements: [this.model.id] });
}
}
}
onResize = () => {};
onRotate = () => {};
/**
* Called when the view is destroyed.
* Override this method requires calling `super.onDestroyed()`.
*/
onDestroyed() {
this._isConnected = false;
this.disposable.dispose();
this._handlers.clear();
}
render(_: RendererContext) {}
}