L-Sun
2025-02-28 08:23:26 +00:00
parent f1df774188
commit d476d3b1df
27 changed files with 356 additions and 528 deletions

View File

@@ -153,6 +153,10 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
return this._richTextElement.inlineEditor;
}
get inlineEditorContainer() {
return this._richTextElement.inlineEditorContainer;
}
override connectedCallback() {
super.connectedCallback();

View File

@@ -1,164 +0,0 @@
import { IS_IOS } from '@blocksuite/global/env';
import type * as GlobalTypes from '@blocksuite/global/types';
import { DisposableGroup } from '@blocksuite/global/utils';
import { signal } from '@preact/signals-core';
import type { ReactiveController, ReactiveControllerHost } from 'lit';
declare type _GLOBAL_ = typeof GlobalTypes;
function notSupportedWarning() {
console.warn('VirtualKeyboard API and VisualViewport API are not supported');
}
export type VirtualKeyboardControllerConfig = {
useScreenHeight: boolean;
inputElement: HTMLElement;
};
export class VirtualKeyboardController implements ReactiveController {
private readonly _disposables = new DisposableGroup();
private readonly _keyboardHeight$ = signal(0);
private readonly _keyboardOpened$ = signal(false);
private readonly _storeInitialInputElementAttributes = () => {
const { inputElement } = this.config;
if (navigator.virtualKeyboard) {
const { overlaysContent } = navigator.virtualKeyboard;
const { virtualKeyboardPolicy } = inputElement;
this._disposables.add(() => {
if (!navigator.virtualKeyboard) return;
navigator.virtualKeyboard.overlaysContent = overlaysContent;
inputElement.virtualKeyboardPolicy = virtualKeyboardPolicy;
});
} else if (visualViewport) {
const { inputMode } = inputElement;
this._disposables.add(() => {
inputElement.inputMode = inputMode;
});
}
};
private readonly _updateKeyboardHeight = () => {
const { virtualKeyboard } = navigator;
if (virtualKeyboard) {
this._keyboardOpened$.value = virtualKeyboard.boundingRect.height > 0;
this._keyboardHeight$.value = virtualKeyboard.boundingRect.height;
} else if (visualViewport) {
const windowHeight = this.config.useScreenHeight
? window.screen.height
: window.innerHeight;
/**
* ┌───────────────┐ - window top
* │ │
* │ │
* │ │
* │ │
* │ │
* └───────────────┘ - keyboard top --
* │ │ │ keyboard height in layout viewport
* └───────────────┘ - page(html) bottom --
* │ │ │ visualViewport.offsetTop
* └───────────────┘ - window bottom --
*/
this._keyboardOpened$.value = windowHeight - visualViewport.height > 0;
this._keyboardHeight$.value =
windowHeight -
visualViewport.height -
(IS_IOS ? 0 : visualViewport.offsetTop);
} else {
notSupportedWarning();
}
};
hide = () => {
if (navigator.virtualKeyboard) {
navigator.virtualKeyboard.hide();
} else {
this.config.inputElement.inputMode = 'none';
}
};
host: ReactiveControllerHost & {
virtualKeyboardControllerConfig: VirtualKeyboardControllerConfig;
hasUpdated: boolean;
};
show = () => {
if (navigator.virtualKeyboard) {
navigator.virtualKeyboard.show();
} else {
this.config.inputElement.inputMode = '';
}
};
toggle = () => {
if (this.opened) {
this.hide();
} else {
this.show();
}
};
get config() {
return this.host.virtualKeyboardControllerConfig;
}
/**
* Return the height of keyboard in layout viewport
* see comment in the `_updateKeyboardHeight` method
*/
get keyboardHeight() {
return this._keyboardHeight$.value;
}
get opened() {
return this._keyboardOpened$.value;
}
constructor(host: VirtualKeyboardController['host']) {
(this.host = host).addController(this);
}
hostConnected() {
this._storeInitialInputElementAttributes();
const { inputElement } = this.config;
if (navigator.virtualKeyboard) {
navigator.virtualKeyboard.overlaysContent = true;
this.config.inputElement.virtualKeyboardPolicy = 'manual';
this._disposables.addFromEvent(
navigator.virtualKeyboard,
'geometrychange',
this._updateKeyboardHeight
);
} else if (visualViewport) {
this._disposables.addFromEvent(
visualViewport,
'resize',
this._updateKeyboardHeight
);
this._disposables.addFromEvent(
visualViewport,
'scroll',
this._updateKeyboardHeight
);
} else {
notSupportedWarning();
}
this._disposables.addFromEvent(inputElement, 'focus', this.show);
this._disposables.addFromEvent(inputElement, 'blur', this.hide);
this._updateKeyboardHeight();
}
hostDisconnected() {
this._disposables.dispose();
}
}

View File

@@ -1 +0,0 @@
export * from './controller.js';