feat(editor): viewport overlay widget extension (#12035)

Closes: BS-3360

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a new viewport overlay widget, making it available as part of the workspace and enabling its integration into supported pages.

- **Refactor**
  - Updated internal imports and exports to utilize the new viewport overlay widget package.
  - Streamlined widget registration and extension mechanisms for improved modularity.

- **Chores**
  - Added configuration and project references to support the new viewport overlay widget package in the build system.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Saul-Mirone
2025-04-28 14:38:26 +00:00
parent d7be1b3424
commit 4e201ede17
19 changed files with 147 additions and 86 deletions

View File

@@ -39,12 +39,5 @@
"!src/__tests__",
"!dist/__tests__"
],
"version": "0.21.0",
"devDependencies": {
"@types/lodash.groupby": "^4",
"@types/lodash.mergewith": "^4",
"@types/lodash.orderby": "^4",
"@types/lodash.partition": "^4",
"@types/lodash.topairs": "^4"
}
"version": "0.21.0"
}

View File

@@ -0,0 +1,40 @@
{
"name": "@blocksuite/affine-widget-viewport-overlay",
"description": "Affine viewport overlay widget.",
"type": "module",
"scripts": {
"build": "tsc"
},
"sideEffects": false,
"keywords": [],
"author": "toeverything",
"license": "MIT",
"dependencies": {
"@blocksuite/affine-components": "workspace:*",
"@blocksuite/affine-ext-loader": "workspace:*",
"@blocksuite/affine-model": "workspace:*",
"@blocksuite/affine-shared": "workspace:*",
"@blocksuite/global": "workspace:*",
"@blocksuite/icons": "^2.2.12",
"@blocksuite/std": "workspace:*",
"@floating-ui/dom": "^1.6.13",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.12",
"@types/lodash-es": "^4.17.12",
"lit": "^3.2.0",
"lodash-es": "^4.17.21",
"rxjs": "^7.8.1"
},
"exports": {
".": "./src/index.ts",
"./effects": "./src/effects.ts",
"./view": "./src/view.ts"
},
"files": [
"src",
"dist",
"!src/__tests__",
"!dist/__tests__"
],
"version": "0.21.0"
}

View File

@@ -0,0 +1,11 @@
import {
AFFINE_VIEWPORT_OVERLAY_WIDGET,
AffineViewportOverlayWidget,
} from './index';
export function effects() {
customElements.define(
AFFINE_VIEWPORT_OVERLAY_WIDGET,
AffineViewportOverlayWidget
);
}

View File

@@ -0,0 +1,90 @@
import type { RootBlockModel } from '@blocksuite/affine-model';
import { WidgetComponent, WidgetViewExtension } from '@blocksuite/std';
import { css, html } from 'lit';
import { state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { styleMap } from 'lit/directives/style-map.js';
import { literal, unsafeStatic } from 'lit/static-html.js';
export const AFFINE_VIEWPORT_OVERLAY_WIDGET = 'affine-viewport-overlay-widget';
export class AffineViewportOverlayWidget extends WidgetComponent<RootBlockModel> {
static override styles = css`
.affine-viewport-overlay-widget {
position: absolute;
top: 0;
left: 0;
background: transparent;
pointer-events: none;
z-index: calc(var(--affine-z-index-popover) - 1);
}
.affine-viewport-overlay-widget.lock {
pointer-events: auto;
}
`;
override connectedCallback() {
super.connectedCallback();
this.handleEvent(
'dragStart',
() => {
return this._lockViewport;
},
{ global: true }
);
this.handleEvent(
'pointerDown',
() => {
return this._lockViewport;
},
{ global: true }
);
this.handleEvent(
'click',
() => {
return this._lockViewport;
},
{ global: true }
);
}
lock() {
this._lockViewport = true;
}
override render() {
const classes = classMap({
'affine-viewport-overlay-widget': true,
lock: this._lockViewport,
});
const style = styleMap({
width: `${this._lockViewport ? '100vw' : '0'}`,
height: `${this._lockViewport ? '100%' : '0'}`,
});
return html` <div class=${classes} style=${style}></div> `;
}
toggleLock() {
this._lockViewport = !this._lockViewport;
}
unlock() {
this._lockViewport = false;
}
@state()
private accessor _lockViewport = false;
}
export const viewportOverlayWidget = WidgetViewExtension(
'affine:page',
AFFINE_VIEWPORT_OVERLAY_WIDGET,
literal`${unsafeStatic(AFFINE_VIEWPORT_OVERLAY_WIDGET)}`
);
declare global {
interface HTMLElementTagNameMap {
[AFFINE_VIEWPORT_OVERLAY_WIDGET]: AffineViewportOverlayWidget;
}
}

View File

@@ -0,0 +1,21 @@
import {
type ViewExtensionContext,
ViewExtensionProvider,
} from '@blocksuite/affine-ext-loader';
import { effects } from './effects';
import { viewportOverlayWidget } from './index';
export class ViewportOverlayViewExtension extends ViewExtensionProvider {
override name = 'affine-viewport-overlay-widget';
override effect() {
super.effect();
effects();
}
override setup(context: ViewExtensionContext) {
super.setup(context);
context.register(viewportOverlayWidget);
}
}

View File

@@ -0,0 +1,17 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
},
"include": ["./src"],
"references": [
{ "path": "../../components" },
{ "path": "../../ext-loader" },
{ "path": "../../model" },
{ "path": "../../shared" },
{ "path": "../../../framework/global" },
{ "path": "../../../framework/std" }
]
}