From 62d8c0c7cbc94905860c69bae69360b9c417b5bc Mon Sep 17 00:00:00 2001 From: L-Sun Date: Thu, 6 Mar 2025 16:12:06 +0000 Subject: [PATCH] refactor(editor): adjust folder structure for slash menu extension (#10588) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close [BS-2743](https://linear.app/affine-design/issue/BS-2743/slash-menu插件化:调整文件夹结构) This PR move slash menu from `affine-root-block` to `widget-affine-slash-menu`, and make it as a `WidgetViewExtension` --- blocksuite/affine/block-root/package.json | 1 + .../block-root/src/common-specs/index.ts | 4 +- .../block-root/src/common-specs/widgets.ts | 6 - blocksuite/affine/block-root/src/effects.ts | 11 - blocksuite/affine/block-root/src/types.ts | 2 +- .../affine/block-root/src/utils/misc.ts | 1 + .../affine/block-root/src/widgets/index.ts | 9 - .../widgets/linked-doc/linked-doc-popover.ts | 2 +- blocksuite/affine/block-root/tsconfig.json | 1 + blocksuite/affine/shared/src/utils/index.ts | 1 + .../src/utils/popper-position.ts} | 4 +- blocksuite/affine/widget-slash-menu/README.md | 1 + .../affine/widget-slash-menu/package.json | 51 ++++ .../src}/config.ts | 225 +++++++++--------- .../affine/widget-slash-menu/src/effects.ts | 14 ++ .../widget-slash-menu/src/extensions.ts | 18 ++ .../affine/widget-slash-menu/src/index.ts | 3 + .../src}/slash-menu-popover.ts | 6 +- .../src}/styles.ts | 0 .../src}/tooltips/attachment.ts | 0 .../src}/tooltips/bold-text.ts | 0 .../src}/tooltips/bulleted-list.ts | 0 .../src}/tooltips/code-block.ts | 0 .../src}/tooltips/copy.ts | 0 .../src}/tooltips/delete.ts | 0 .../src}/tooltips/divider.ts | 0 .../src}/tooltips/edgeless.ts | 0 .../src}/tooltips/empty.ts | 0 .../src}/tooltips/figma.ts | 0 .../src}/tooltips/github-repo.ts | 0 .../src}/tooltips/heading-1.ts | 0 .../src}/tooltips/heading-2.ts | 0 .../src}/tooltips/heading-3.ts | 0 .../src}/tooltips/heading-4.ts | 0 .../src}/tooltips/heading-5.ts | 0 .../src}/tooltips/heading-6.ts | 0 .../src}/tooltips/index.ts | 78 +++--- .../src}/tooltips/italic.ts | 0 .../src}/tooltips/kanban-view.ts | 0 .../src}/tooltips/linear.ts | 0 .../src}/tooltips/link-doc.ts | 0 .../src}/tooltips/link.ts | 0 .../src}/tooltips/move-down.ts | 0 .../src}/tooltips/move-up.ts | 0 .../src}/tooltips/new-doc.ts | 0 .../src}/tooltips/now.ts | 0 .../src}/tooltips/numbered-list.ts | 0 .../src}/tooltips/pdf.ts | 0 .../src}/tooltips/photo.ts | 0 .../src}/tooltips/quote.ts | 0 .../src}/tooltips/strikethrough.ts | 0 .../src}/tooltips/table-view.ts | 0 .../src}/tooltips/text.ts | 0 .../src}/tooltips/to-do-list.ts | 0 .../src}/tooltips/today.ts | 0 .../src}/tooltips/tomorrow.ts | 0 .../src}/tooltips/tweet.ts | 0 .../src}/tooltips/underline.ts | 0 .../src}/tooltips/yesterday.ts | 0 .../src}/tooltips/youtube-video.ts | 0 .../src}/utils.ts | 27 ++- .../src/widget.ts} | 24 +- .../affine/widget-slash-menu/tsconfig.json | 27 +++ blocksuite/blocks/package.json | 1 + blocksuite/blocks/src/effects.ts | 2 + blocksuite/blocks/src/index.ts | 3 + blocksuite/blocks/tsconfig.json | 1 + .../ai/entries/slash-menu/setup-slash-menu.ts | 31 +-- .../extensions/entry/enable-mobile.ts | 4 +- .../extensions/quick-search-service.ts | 9 +- tools/utils/src/workspace.gen.ts | 25 ++ tsconfig.json | 1 + yarn.lock | 34 ++- 73 files changed, 397 insertions(+), 230 deletions(-) rename blocksuite/affine/{block-root/src/utils/position.ts => shared/src/utils/popper-position.ts} (97%) create mode 100644 blocksuite/affine/widget-slash-menu/README.md create mode 100644 blocksuite/affine/widget-slash-menu/package.json rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/config.ts (79%) create mode 100644 blocksuite/affine/widget-slash-menu/src/effects.ts create mode 100644 blocksuite/affine/widget-slash-menu/src/extensions.ts create mode 100644 blocksuite/affine/widget-slash-menu/src/index.ts rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/slash-menu-popover.ts (99%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/styles.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/attachment.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/bold-text.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/bulleted-list.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/code-block.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/copy.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/delete.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/divider.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/edgeless.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/empty.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/figma.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/github-repo.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/heading-1.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/heading-2.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/heading-3.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/heading-4.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/heading-5.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/heading-6.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/index.ts (62%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/italic.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/kanban-view.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/linear.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/link-doc.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/link.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/move-down.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/move-up.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/new-doc.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/now.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/numbered-list.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/pdf.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/photo.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/quote.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/strikethrough.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/table-view.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/text.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/to-do-list.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/today.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/tomorrow.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/tweet.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/underline.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/yesterday.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/tooltips/youtube-video.ts (100%) rename blocksuite/affine/{block-root/src/widgets/slash-menu => widget-slash-menu/src}/utils.ts (81%) rename blocksuite/affine/{block-root/src/widgets/slash-menu/index.ts => widget-slash-menu/src/widget.ts} (91%) create mode 100644 blocksuite/affine/widget-slash-menu/tsconfig.json diff --git a/blocksuite/affine/block-root/package.json b/blocksuite/affine/block-root/package.json index 2919dd7374..e1f97965c5 100644 --- a/blocksuite/affine/block-root/package.json +++ b/blocksuite/affine/block-root/package.json @@ -36,6 +36,7 @@ "@blocksuite/affine-widget-frame-title": "workspace:*", "@blocksuite/affine-widget-remote-selection": "workspace:*", "@blocksuite/affine-widget-scroll-anchoring": "workspace:*", + "@blocksuite/affine-widget-slash-menu": "workspace:*", "@blocksuite/affine-widget-toolbar": "workspace:*", "@blocksuite/block-std": "workspace:*", "@blocksuite/data-view": "workspace:*", diff --git a/blocksuite/affine/block-root/src/common-specs/index.ts b/blocksuite/affine/block-root/src/common-specs/index.ts index df6da2301d..69f2849169 100644 --- a/blocksuite/affine/block-root/src/common-specs/index.ts +++ b/blocksuite/affine/block-root/src/common-specs/index.ts @@ -12,6 +12,7 @@ import { import { dragHandleWidget } from '@blocksuite/affine-widget-drag-handle'; import { docRemoteSelectionWidget } from '@blocksuite/affine-widget-remote-selection'; import { scrollAnchoringWidget } from '@blocksuite/affine-widget-scroll-anchoring'; +import { SlashMenuExtension } from '@blocksuite/affine-widget-slash-menu'; import { toolbarWidget } from '@blocksuite/affine-widget-toolbar'; import { BlockFlavourIdentifier, @@ -25,7 +26,6 @@ import { innerModalWidget, linkedDocWidget, modalWidget, - slashMenuWidget, viewportOverlayWidget, } from './widgets'; @@ -42,7 +42,7 @@ export const CommonSpecs: ExtensionType[] = [ modalWidget, innerModalWidget, - slashMenuWidget, + SlashMenuExtension, linkedDocWidget, dragHandleWidget, docRemoteSelectionWidget, diff --git a/blocksuite/affine/block-root/src/common-specs/widgets.ts b/blocksuite/affine/block-root/src/common-specs/widgets.ts index c72600a173..95b47cc97d 100644 --- a/blocksuite/affine/block-root/src/common-specs/widgets.ts +++ b/blocksuite/affine/block-root/src/common-specs/widgets.ts @@ -4,7 +4,6 @@ import { literal, unsafeStatic } from 'lit/static-html.js'; import { AFFINE_INNER_MODAL_WIDGET } from '../widgets/inner-modal/inner-modal.js'; import { AFFINE_LINKED_DOC_WIDGET } from '../widgets/linked-doc/config.js'; import { AFFINE_MODAL_WIDGET } from '../widgets/modal/modal.js'; -import { AFFINE_SLASH_MENU_WIDGET } from '../widgets/slash-menu/index.js'; import { AFFINE_VIEWPORT_OVERLAY_WIDGET } from '../widgets/viewport-overlay/viewport-overlay.js'; export const modalWidget = WidgetViewExtension( @@ -17,11 +16,6 @@ export const innerModalWidget = WidgetViewExtension( AFFINE_INNER_MODAL_WIDGET, literal`${unsafeStatic(AFFINE_INNER_MODAL_WIDGET)}` ); -export const slashMenuWidget = WidgetViewExtension( - 'affine:page', - AFFINE_SLASH_MENU_WIDGET, - literal`${unsafeStatic(AFFINE_SLASH_MENU_WIDGET)}` -); export const linkedDocWidget = WidgetViewExtension( 'affine:page', AFFINE_LINKED_DOC_WIDGET, diff --git a/blocksuite/affine/block-root/src/effects.ts b/blocksuite/affine/block-root/src/effects.ts index f0d004b2fe..e07d37690c 100644 --- a/blocksuite/affine/block-root/src/effects.ts +++ b/blocksuite/affine/block-root/src/effects.ts @@ -106,14 +106,6 @@ import { AFFINE_PAGE_DRAGGING_AREA_WIDGET, AffinePageDraggingAreaWidget, } from './widgets/page-dragging-area/page-dragging-area.js'; -import { - AFFINE_SLASH_MENU_WIDGET, - AffineSlashMenuWidget, -} from './widgets/slash-menu/index.js'; -import { - InnerSlashMenu, - SlashMenu, -} from './widgets/slash-menu/slash-menu-popover.js'; import { AFFINE_SURFACE_REF_TOOLBAR, AffineSurfaceRefToolbar, @@ -156,7 +148,6 @@ function registerWidgets() { AffinePageDraggingAreaWidget ); customElements.define(AFFINE_IMAGE_TOOLBAR_WIDGET, AffineImageToolbarWidget); - customElements.define(AFFINE_SLASH_MENU_WIDGET, AffineSlashMenuWidget); customElements.define( AFFINE_VIEWPORT_OVERLAY_WIDGET, AffineViewportOverlayWidget @@ -274,8 +265,6 @@ function registerEdgelessEditorComponents() { function registerMiscComponents() { // Modal and menu components customElements.define('affine-custom-modal', AffineCustomModal); - customElements.define('affine-slash-menu', SlashMenu); - customElements.define('inner-slash-menu', InnerSlashMenu); // Loading and preview components customElements.define('loader-element', Loader); diff --git a/blocksuite/affine/block-root/src/types.ts b/blocksuite/affine/block-root/src/types.ts index 409b693d73..222e187577 100644 --- a/blocksuite/affine/block-root/src/types.ts +++ b/blocksuite/affine/block-root/src/types.ts @@ -4,6 +4,7 @@ import type { AFFINE_DOC_REMOTE_SELECTION_WIDGET, AFFINE_EDGELESS_REMOTE_SELECTION_WIDGET, } from '@blocksuite/affine-widget-remote-selection'; +import type { AFFINE_SLASH_MENU_WIDGET } from '@blocksuite/affine-widget-slash-menu'; import type { EdgelessRootBlockComponent } from './edgeless/edgeless-root-block.js'; import type { PageRootBlockComponent } from './page/page-root-block.js'; @@ -14,7 +15,6 @@ import type { AFFINE_INNER_MODAL_WIDGET } from './widgets/inner-modal/inner-moda import type { AFFINE_LINKED_DOC_WIDGET } from './widgets/linked-doc/config.js'; import type { AFFINE_MODAL_WIDGET } from './widgets/modal/modal.js'; import type { AFFINE_PAGE_DRAGGING_AREA_WIDGET } from './widgets/page-dragging-area/page-dragging-area.js'; -import type { AFFINE_SLASH_MENU_WIDGET } from './widgets/slash-menu/index.js'; import type { AFFINE_VIEWPORT_OVERLAY_WIDGET } from './widgets/viewport-overlay/viewport-overlay.js'; export type PageRootBlockWidgetName = diff --git a/blocksuite/affine/block-root/src/utils/misc.ts b/blocksuite/affine/block-root/src/utils/misc.ts index c17b9182a6..43ad2ebbe9 100644 --- a/blocksuite/affine/block-root/src/utils/misc.ts +++ b/blocksuite/affine/block-root/src/utils/misc.ts @@ -1,3 +1,4 @@ +// TODO(@L-Sun): remove these utils export function formatDate(date: Date) { // yyyy-mm-dd const year = date.getFullYear(); diff --git a/blocksuite/affine/block-root/src/widgets/index.ts b/blocksuite/affine/block-root/src/widgets/index.ts index 97f27644bf..3685632df6 100644 --- a/blocksuite/affine/block-root/src/widgets/index.ts +++ b/blocksuite/affine/block-root/src/widgets/index.ts @@ -21,15 +21,6 @@ export { export { AffineLinkedDocWidget } from './linked-doc/index.js'; export { AffineModalWidget } from './modal/modal.js'; export { AffinePageDraggingAreaWidget } from './page-dragging-area/page-dragging-area.js'; -export { - type AffineSlashMenuActionItem, - type AffineSlashMenuContext, - type AffineSlashMenuGroupDivider, - type AffineSlashMenuItem, - type AffineSlashMenuItemGenerator, - AffineSlashMenuWidget, - type AffineSlashSubMenu, -} from './slash-menu/index.js'; export { AffineSurfaceRefToolbar } from './surface-ref-toolbar/surface-ref-toolbar.js'; export * from './viewport-overlay/viewport-overlay.js'; export { AffineFrameTitleWidget } from '@blocksuite/affine-widget-frame-title'; diff --git a/blocksuite/affine/block-root/src/widgets/linked-doc/linked-doc-popover.ts b/blocksuite/affine/block-root/src/widgets/linked-doc/linked-doc-popover.ts index 8e96d591db..d9899f8621 100644 --- a/blocksuite/affine/block-root/src/widgets/linked-doc/linked-doc-popover.ts +++ b/blocksuite/affine/block-root/src/widgets/linked-doc/linked-doc-popover.ts @@ -8,6 +8,7 @@ import { unsafeCSSVar } from '@blocksuite/affine-shared/theme'; import { createKeydownObserver, getCurrentNativeRange, + getPopperPosition, getViewportElement, } from '@blocksuite/affine-shared/utils'; import { PropTypes, requiredProperties } from '@blocksuite/block-std'; @@ -20,7 +21,6 @@ import { property, query, queryAll, state } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; import throttle from 'lodash-es/throttle'; -import { getPopperPosition } from '../../utils/position.js'; import type { LinkedDocContext, LinkedMenuGroup } from './config.js'; import { linkedDocPopoverStyles } from './styles.js'; import { resolveSignal } from './utils.js'; diff --git a/blocksuite/affine/block-root/tsconfig.json b/blocksuite/affine/block-root/tsconfig.json index 8769d842b7..873c196502 100644 --- a/blocksuite/affine/block-root/tsconfig.json +++ b/blocksuite/affine/block-root/tsconfig.json @@ -30,6 +30,7 @@ { "path": "../widget-frame-title" }, { "path": "../widget-remote-selection" }, { "path": "../widget-scroll-anchoring" }, + { "path": "../widget-slash-menu" }, { "path": "../widget-toolbar" }, { "path": "../../framework/block-std" }, { "path": "../data-view" }, diff --git a/blocksuite/affine/shared/src/utils/index.ts b/blocksuite/affine/shared/src/utils/index.ts index 789a2ef0c2..82b4f350f2 100644 --- a/blocksuite/affine/shared/src/utils/index.ts +++ b/blocksuite/affine/shared/src/utils/index.ts @@ -14,6 +14,7 @@ export * from './insert'; export * from './is-abort-error'; export * from './math'; export * from './model'; +export * from './popper-position'; export * from './print-to-pdf'; export * from './reference'; export * from './reordering'; diff --git a/blocksuite/affine/block-root/src/utils/position.ts b/blocksuite/affine/shared/src/utils/popper-position.ts similarity index 97% rename from blocksuite/affine/block-root/src/utils/position.ts rename to blocksuite/affine/shared/src/utils/popper-position.ts index 65da8a84bc..4e6e80333d 100644 --- a/blocksuite/affine/block-root/src/utils/position.ts +++ b/blocksuite/affine/shared/src/utils/popper-position.ts @@ -18,7 +18,7 @@ type CollisionBox = { edgeGap?: number; }; -export function calcSafeCoordinate({ +function calcSafeCoordinate({ positioningPoint, objRect = { width: 0, height: 0 }, boundaryRect = document.body.getBoundingClientRect(), @@ -50,7 +50,7 @@ export function calcSafeCoordinate({ * * Please give preference to {@link getPopperPosition} */ -export function compareTopAndBottomSpace( +function compareTopAndBottomSpace( obj: { getBoundingClientRect: () => DOMRect }, container = document.body, gap = 20 diff --git a/blocksuite/affine/widget-slash-menu/README.md b/blocksuite/affine/widget-slash-menu/README.md new file mode 100644 index 0000000000..3438a1ff26 --- /dev/null +++ b/blocksuite/affine/widget-slash-menu/README.md @@ -0,0 +1 @@ +# widget-slash-menu diff --git a/blocksuite/affine/widget-slash-menu/package.json b/blocksuite/affine/widget-slash-menu/package.json new file mode 100644 index 0000000000..c67685e3d1 --- /dev/null +++ b/blocksuite/affine/widget-slash-menu/package.json @@ -0,0 +1,51 @@ +{ + "name": "@blocksuite/affine-widget-slash-menu", + "description": "Affine slash menu widget.", + "type": "module", + "scripts": { + "build": "tsc", + "test:unit": "nx vite:test --run --passWithNoTests", + "test:unit:coverage": "nx vite:test --run --coverage", + "test:e2e": "playwright test" + }, + "sideEffects": false, + "keywords": [], + "author": "toeverything", + "license": "MIT", + "dependencies": { + "@blocksuite/affine-block-attachment": "workspace:*", + "@blocksuite/affine-block-database": "workspace:*", + "@blocksuite/affine-block-embed": "workspace:*", + "@blocksuite/affine-block-image": "workspace:*", + "@blocksuite/affine-block-latex": "workspace:*", + "@blocksuite/affine-block-note": "workspace:*", + "@blocksuite/affine-block-surface": "workspace:*", + "@blocksuite/affine-block-surface-ref": "workspace:*", + "@blocksuite/affine-block-table": "workspace:*", + "@blocksuite/affine-components": "workspace:*", + "@blocksuite/affine-shared": "workspace:*", + "@blocksuite/block-std": "workspace:*", + "@blocksuite/data-view": "workspace:*", + "@blocksuite/global": "workspace:*", + "@blocksuite/icons": "^2.2.4", + "@blocksuite/inline": "workspace:*", + "@blocksuite/store": "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" + }, + "exports": { + ".": "./src/index.ts", + "./effects": "./src/effects.ts" + }, + "files": [ + "src", + "dist", + "!src/__tests__", + "!dist/__tests__" + ], + "version": "0.20.0" +} diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/config.ts b/blocksuite/affine/widget-slash-menu/src/config.ts similarity index 79% rename from blocksuite/affine/block-root/src/widgets/slash-menu/config.ts rename to blocksuite/affine/widget-slash-menu/src/config.ts index 9f6d58c7c1..786458092f 100644 --- a/blocksuite/affine/block-root/src/widgets/slash-menu/config.ts +++ b/blocksuite/affine/widget-slash-menu/src/config.ts @@ -57,8 +57,8 @@ import { createDefaultDoc, openFileOrFiles, } from '@blocksuite/affine-shared/utils'; +import type { BlockStdScope } from '@blocksuite/block-std'; import { viewPresets } from '@blocksuite/data-view/view-presets'; -import { assertType } from '@blocksuite/global/utils'; import { DualLinkIcon, ExportToPdfIcon, @@ -74,16 +74,15 @@ import type { BlockModel } from '@blocksuite/store'; import { Slice, Text } from '@blocksuite/store'; import type { TemplateResult } from 'lit'; -import type { RootBlockComponent } from '../../types.js'; -import { formatDate, formatTime } from '../../utils/misc.js'; -import type { AffineLinkedDocWidget } from '../linked-doc/index.js'; -import { type SlashMenuTooltip, slashMenuToolTips } from './tooltips/index.js'; +import { type SlashMenuTooltip, slashMenuToolTips } from './tooltips'; import { createConversionItem, createTextFormatItem, + formatDate, + formatTime, insideEdgelessText, tryRemoveEmptyLine, -} from './utils.js'; +} from './utils'; export type SlashMenuConfig = { triggerKeys: string[]; @@ -136,7 +135,7 @@ export type SlashMenuItemGenerator = ( ) => (SlashMenuGroupDivider | SlashMenuActionItem | SlashSubMenu)[]; export type SlashMenuContext = { - rootComponent: RootBlockComponent; + std: BlockStdScope; model: BlockModel; }; @@ -183,7 +182,7 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { showWhen: ({ model }) => { return model.doc.get(FeatureFlagService).getFlag('enable_callout'); }, - action: ({ model, rootComponent }) => { + action: ({ model, std }) => { const { doc } = model; const parent = doc.getParent(model); if (!parent) return; @@ -194,11 +193,11 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { if (!calloutId) return; const paragraphId = doc.addBlock('affine:paragraph', {}, calloutId); if (!paragraphId) return; - rootComponent.updateComplete + std.host.updateComplete .then(() => { - const paragraph = rootComponent.std.view.getBlock(paragraphId); + const paragraph = std.view.getBlock(paragraphId); if (!paragraph) return; - rootComponent.std.command.exec(focusBlockEnd, { + std.command.exec(focusBlockEnd, { focusBlock: paragraph, }); }) @@ -211,8 +210,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { description: 'Create a equation block.', icon: TeXIcon(), alias: ['inlineMath, inlineEquation', 'inlineLatex'], - action: ({ rootComponent }) => { - rootComponent.std.command + action: ({ std }) => { + std.command .chain() .pipe(getTextSelectionCommand) .pipe(insertInlineLatex) @@ -245,9 +244,9 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { tooltip: slashMenuToolTips['New Doc'], showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:embed-linked-doc'), - action: ({ rootComponent, model }) => { - const newDoc = createDefaultDoc(rootComponent.doc.workspace); - insertContent(rootComponent.host, model, REFERENCE_NODE, { + action: ({ std, model }) => { + const newDoc = createDefaultDoc(std.host.doc.workspace); + insertContent(std.host, model, REFERENCE_NODE, { reference: { type: 'LinkedPage', pageId: newDoc.id, @@ -261,33 +260,36 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { icon: LinkedDocIcon, tooltip: slashMenuToolTips['Linked Doc'], alias: ['dual link'], - showWhen: ({ rootComponent, model }) => { - const { std } = rootComponent; + showWhen: ({ std, model }) => { + const root = model.doc.root; + if (!root) return false; const linkedDocWidget = std.view.getWidget( 'affine-linked-doc-widget', - rootComponent.model.id + root.id ); if (!linkedDocWidget) return false; return model.doc.schema.flavourSchemaMap.has('affine:embed-linked-doc'); }, - action: ({ model, rootComponent }) => { - const { std } = rootComponent; - + action: ({ model, std }) => { + const root = model.doc.root; + if (!root) return; const linkedDocWidget = std.view.getWidget( 'affine-linked-doc-widget', - rootComponent.model.id + root.id ); if (!linkedDocWidget) return; - assertType(linkedDocWidget); - + // TODO(@L-Sun): make linked-doc-widget as extension + // @ts-expect-error same as above const triggerKey = linkedDocWidget.config.triggerKeys[0]; - insertContent(rootComponent.host, model, triggerKey); + insertContent(std.host, model, triggerKey); - const inlineEditor = getInlineEditorByModel(rootComponent.host, model); + const inlineEditor = getInlineEditorByModel(std.host, model); // Wait for range to be updated inlineEditor?.slots.inlineRangeSync.once(() => { + // TODO(@L-Sun): make linked-doc-widget as extension + // @ts-expect-error same as above linkedDocWidget.show({ addTriggerKey: true }); }); }, @@ -301,8 +303,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { icon: TableIcon(), tooltip: slashMenuToolTips['Table View'], showWhen: ({ model }) => !insideEdgelessText(model), - action: ({ rootComponent }) => { - rootComponent.std.command + action: ({ std }) => { + std.command .chain() .pipe(getSelectedModelsCommand) .pipe(insertTableBlockCommand, { @@ -311,8 +313,7 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { }) .pipe(({ insertedTableBlockId }) => { if (insertedTableBlockId) { - const telemetry = - rootComponent.std.getOptional(TelemetryProvider); + const telemetry = std.getOptional(TelemetryProvider); telemetry?.track('BlockCreated', { blockType: 'affine:table', }); @@ -328,8 +329,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { tooltip: slashMenuToolTips['Image'], showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:image'), - action: async ({ rootComponent }) => { - const [success, ctx] = rootComponent.std.command + action: async ({ std }) => { + const [success, ctx] = std.command .chain() .pipe(getSelectedModelsCommand) .pipe(insertImagesCommand, { removeEmptyLine: true }) @@ -345,14 +346,15 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { tooltip: slashMenuToolTips['Link'], showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:bookmark'), - action: async ({ rootComponent, model }) => { - const parentModel = rootComponent.doc.getParent(model); + action: async ({ std, model }) => { + const { host } = std; + const parentModel = host.doc.getParent(model); if (!parentModel) { return; } const index = parentModel.children.indexOf(model) + 1; await toggleEmbedCardCreateModal( - rootComponent.host, + host, 'Links', 'The added link will be displayed as a card view.', { mode: 'page', parentModel, index } @@ -368,19 +370,13 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { alias: ['file'], showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:attachment'), - action: async ({ rootComponent, model }) => { + action: async ({ std, model }) => { const file = await openFileOrFiles(); if (!file) return; - const maxFileSize = - rootComponent.std.store.get(FileSizeLimitService).maxFileSize; + const maxFileSize = std.store.get(FileSizeLimitService).maxFileSize; - await addSiblingAttachmentBlocks( - rootComponent.host, - [file], - maxFileSize, - model - ); + await addSiblingAttachmentBlocks(std.host, [file], maxFileSize, model); tryRemoveEmptyLine(model); }, }, @@ -391,15 +387,14 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { tooltip: slashMenuToolTips['PDF'], showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:attachment'), - action: async ({ rootComponent, model }) => { + action: async ({ std, model }) => { const file = await openFileOrFiles(); if (!file) return; - const maxFileSize = - rootComponent.std.store.get(FileSizeLimitService).maxFileSize; + const maxFileSize = std.store.get(FileSizeLimitService).maxFileSize; await addSiblingAttachmentBlocks( - rootComponent.host, + std.host, [file], maxFileSize, model, @@ -416,14 +411,15 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { tooltip: slashMenuToolTips['YouTube'], showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:embed-youtube'), - action: async ({ rootComponent, model }) => { - const parentModel = rootComponent.doc.getParent(model); + action: async ({ std, model }) => { + const { host } = std; + const parentModel = host.doc.getParent(model); if (!parentModel) { return; } const index = parentModel.children.indexOf(model) + 1; await toggleEmbedCardCreateModal( - rootComponent.host, + host, 'YouTube', 'The added YouTube video link will be displayed as an embed view.', { mode: 'page', parentModel, index } @@ -438,14 +434,15 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { tooltip: slashMenuToolTips['Github'], showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:embed-github'), - action: async ({ rootComponent, model }) => { - const parentModel = rootComponent.doc.getParent(model); + action: async ({ std, model }) => { + const { host } = std; + const parentModel = host.doc.getParent(model); if (!parentModel) { return; } const index = parentModel.children.indexOf(model) + 1; await toggleEmbedCardCreateModal( - rootComponent.host, + host, 'GitHub', 'The added GitHub issue or pull request link will be displayed as a card view.', { mode: 'page', parentModel, index } @@ -462,14 +459,15 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { tooltip: slashMenuToolTips['Figma'], showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:embed-figma'), - action: async ({ rootComponent, model }) => { - const parentModel = rootComponent.doc.getParent(model); + action: async ({ std, model }) => { + const { host } = std; + const parentModel = host.doc.getParent(model); if (!parentModel) { return; } const index = parentModel.children.indexOf(model) + 1; await toggleEmbedCardCreateModal( - rootComponent.host, + host, 'Figma', 'The added Figma link will be displayed as an embed view.', { mode: 'page', parentModel, index } @@ -483,14 +481,15 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { icon: LoomIcon, showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:embed-loom'), - action: async ({ rootComponent, model }) => { - const parentModel = rootComponent.doc.getParent(model); + action: async ({ std, model }) => { + const { host } = std; + const parentModel = host.doc.getParent(model); if (!parentModel) { return; } const index = parentModel.children.indexOf(model) + 1; await toggleEmbedCardCreateModal( - rootComponent.host, + host, 'Loom', 'The added Loom video link will be displayed as an embed view.', { mode: 'page', parentModel, index } @@ -504,8 +503,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { description: 'Create a equation block.', icon: TeXIcon(), alias: ['mathBlock, equationBlock', 'latexBlock'], - action: ({ rootComponent }) => { - rootComponent.std.command + action: ({ std }) => { + std.command .chain() .pipe(getSelectedModelsCommand) .pipe(insertLatexBlockCommand, { @@ -519,24 +518,24 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { // TODO(@L-Sun): Linear // --------------------------------------------------------- - ({ model, rootComponent }) => { - const { doc } = rootComponent; + ({ model, std }) => { + const { host } = std; - const surfaceModel = getSurfaceBlock(doc); + const surfaceModel = getSurfaceBlock(host.doc); if (!surfaceModel) return []; - const parent = doc.getParent(model); + const parent = host.doc.getParent(model); if (!parent) return []; - const frameModels = doc + const frameModels = host.doc .getBlocksByFlavour('affine:frame') .map(block => block.model as FrameBlockModel); const frameItems = frameModels.map(frameModel => ({ name: 'Frame: ' + frameModel.title, icon: FrameIcon(), - action: ({ rootComponent }) => { - rootComponent.std.command + action: ({ std }) => { + std.command .chain() .pipe(getSelectedModelsCommand) .pipe(insertSurfaceRefBlockCommand, { @@ -553,7 +552,7 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { name: 'Group: ' + group.title.toString(), icon: GroupingIcon(), action: () => { - rootComponent.std.command + std.command .chain() .pipe(getSelectedModelsCommand) .pipe(insertSurfaceRefBlockCommand, { @@ -594,8 +593,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { icon: TodayIcon, tooltip: slashMenuToolTips['Today'], description: formatDate(now), - action: ({ rootComponent, model }) => { - insertContent(rootComponent.host, model, formatDate(now)); + action: ({ std, model }) => { + insertContent(std.host, model, formatDate(now)); }, }, { @@ -603,10 +602,10 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { icon: TomorrowIcon, tooltip: slashMenuToolTips['Tomorrow'], description: formatDate(tomorrow), - action: ({ rootComponent, model }) => { + action: ({ std, model }) => { const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); - insertContent(rootComponent.host, model, formatDate(tomorrow)); + insertContent(std.host, model, formatDate(tomorrow)); }, }, { @@ -614,10 +613,10 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { icon: YesterdayIcon, tooltip: slashMenuToolTips['Yesterday'], description: formatDate(yesterday), - action: ({ rootComponent, model }) => { + action: ({ std, model }) => { const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); - insertContent(rootComponent.host, model, formatDate(yesterday)); + insertContent(std.host, model, formatDate(yesterday)); }, }, { @@ -625,8 +624,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { icon: NowIcon, tooltip: slashMenuToolTips['Now'], description: formatTime(now), - action: ({ rootComponent, model }) => { - insertContent(rootComponent.host, model, formatTime(now)); + action: ({ std, model }) => { + insertContent(std.host, model, formatTime(now)); }, }, ]; @@ -643,8 +642,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:database') && !insideEdgelessText(model), - action: ({ rootComponent }) => { - rootComponent.std.command + action: ({ std }) => { + std.command .chain() .pipe(getSelectedModelsCommand) .pipe(insertDatabaseBlockCommand, { @@ -654,8 +653,7 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { }) .pipe(({ insertedDatabaseBlockId }) => { if (insertedDatabaseBlockId) { - const telemetry = - rootComponent.std.getOptional(TelemetryProvider); + const telemetry = std.getOptional(TelemetryProvider); telemetry?.track('BlockCreated', { blockType: 'affine:database', }); @@ -674,21 +672,22 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { !insideEdgelessText(model) && !!model.doc.get(FeatureFlagService).getFlag('enable_block_query'), - action: ({ model, rootComponent }) => { - const parent = rootComponent.doc.getParent(model); + action: ({ model, std }) => { + const { host } = std; + const parent = host.doc.getParent(model); if (!parent) return; const index = parent.children.indexOf(model); - const id = rootComponent.doc.addBlock( + const id = host.doc.addBlock( 'affine:data-view', {}, - rootComponent.doc.getParent(model), + host.doc.getParent(model), index + 1 ); - const dataViewModel = rootComponent.doc.getBlock(id)!; + const dataViewModel = host.doc.getBlock(id)!; Promise.resolve() .then(() => { - const dataView = rootComponent.std.view.getBlock( + const dataView = std.view.getBlock( dataViewModel.id ) as DataViewBlockComponent | null; dataView?.dataSource.viewManager.viewAdd('table'); @@ -706,8 +705,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has('affine:database') && !insideEdgelessText(model), - action: ({ rootComponent }) => { - rootComponent.std.command + action: ({ std }) => { + std.command .chain() .pipe(getSelectedModelsCommand) .pipe(insertDatabaseBlockCommand, { @@ -717,8 +716,7 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { }) .pipe(({ insertedDatabaseBlockId }) => { if (insertedDatabaseBlockId) { - const telemetry = - rootComponent.std.getOptional(TelemetryProvider); + const telemetry = std.getOptional(TelemetryProvider); telemetry?.track('BlockCreated', { blockType: 'affine:database', }); @@ -735,15 +733,15 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { description: 'Shift this line up.', icon: ArrowUpBigIcon, tooltip: slashMenuToolTips['Move Up'], - action: ({ rootComponent, model }) => { - const doc = rootComponent.doc; - const previousSiblingModel = doc.getPrev(model); + action: ({ std, model }) => { + const { host } = std; + const previousSiblingModel = host.doc.getPrev(model); if (!previousSiblingModel) return; - const parentModel = doc.getParent(previousSiblingModel); + const parentModel = host.doc.getParent(previousSiblingModel); if (!parentModel) return; - doc.moveBlocks([model], parentModel, previousSiblingModel, true); + host.doc.moveBlocks([model], parentModel, previousSiblingModel, true); }, }, { @@ -751,15 +749,15 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { description: 'Shift this line down.', icon: ArrowDownBigIcon, tooltip: slashMenuToolTips['Move Down'], - action: ({ rootComponent, model }) => { - const doc = rootComponent.doc; - const nextSiblingModel = doc.getNext(model); + action: ({ std, model }) => { + const { host } = std; + const nextSiblingModel = host.doc.getNext(model); if (!nextSiblingModel) return; - const parentModel = doc.getParent(nextSiblingModel); + const parentModel = host.doc.getParent(nextSiblingModel); if (!parentModel) return; - doc.moveBlocks([model], parentModel, nextSiblingModel, false); + host.doc.moveBlocks([model], parentModel, nextSiblingModel, false); }, }, { @@ -767,13 +765,13 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { description: 'Copy this line to clipboard.', icon: CopyIcon, tooltip: slashMenuToolTips['Copy'], - action: ({ rootComponent, model }) => { - const slice = Slice.fromModels(rootComponent.std.store, [model]); + action: ({ std, model }) => { + const slice = Slice.fromModels(std.store, [model]); - rootComponent.std.clipboard + std.clipboard .copy(slice) .then(() => { - toast(rootComponent.host, 'Copied to clipboard'); + toast(std.host, 'Copied to clipboard'); }) .catch(e => { console.error(e); @@ -785,12 +783,13 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { description: 'Create a duplicate of this line.', icon: DualLinkIcon(), tooltip: slashMenuToolTips['Copy'], - action: ({ rootComponent, model }) => { + action: ({ std, model }) => { if (!model.text || !(model.text instanceof Text)) { console.error("Can't duplicate a block without text"); return; } - const parent = rootComponent.doc.getParent(model); + const { host } = std; + const parent = host.doc.getParent(model); if (!parent) { console.error( 'Failed to duplicate block! Parent not found: ' + @@ -803,7 +802,7 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { const index = parent.children.indexOf(model); // TODO add clone model util - rootComponent.doc.addBlock( + host.doc.addBlock( model.flavour as never, { type: (model as ParagraphBlockModel).type, @@ -811,7 +810,7 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { // @ts-expect-error FIXME: ts error checked: model.checked, }, - rootComponent.doc.getParent(model), + host.doc.getParent(model), index ); }, @@ -822,8 +821,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = { alias: ['remove'], icon: DeleteIcon, tooltip: slashMenuToolTips['Delete'], - action: ({ rootComponent, model }) => { - rootComponent.doc.deleteBlock(model); + action: ({ std, model }) => { + std.host.doc.deleteBlock(model); }, }, ], diff --git a/blocksuite/affine/widget-slash-menu/src/effects.ts b/blocksuite/affine/widget-slash-menu/src/effects.ts new file mode 100644 index 0000000000..c096ac4fb3 --- /dev/null +++ b/blocksuite/affine/widget-slash-menu/src/effects.ts @@ -0,0 +1,14 @@ +import { InnerSlashMenu, SlashMenu } from './slash-menu-popover'; +import { AFFINE_SLASH_MENU_WIDGET, AffineSlashMenuWidget } from './widget'; + +export function effects() { + customElements.define(AFFINE_SLASH_MENU_WIDGET, AffineSlashMenuWidget); + customElements.define('affine-slash-menu', SlashMenu); + customElements.define('inner-slash-menu', InnerSlashMenu); +} + +declare global { + interface HTMLElementTagNameMap { + [AFFINE_SLASH_MENU_WIDGET]: AffineSlashMenuWidget; + } +} diff --git a/blocksuite/affine/widget-slash-menu/src/extensions.ts b/blocksuite/affine/widget-slash-menu/src/extensions.ts new file mode 100644 index 0000000000..e04fba04e7 --- /dev/null +++ b/blocksuite/affine/widget-slash-menu/src/extensions.ts @@ -0,0 +1,18 @@ +import { WidgetViewExtension } from '@blocksuite/block-std'; +import { type Container } from '@blocksuite/global/di'; +import { Extension } from '@blocksuite/store'; +import { literal, unsafeStatic } from 'lit/static-html.js'; + +import { AFFINE_SLASH_MENU_WIDGET } from './widget'; + +export class SlashMenuExtension extends Extension { + static override setup(di: Container) { + WidgetViewExtension( + 'affine:page', + AFFINE_SLASH_MENU_WIDGET, + literal`${unsafeStatic(AFFINE_SLASH_MENU_WIDGET)}` + ).setup(di); + + di.add(this); + } +} diff --git a/blocksuite/affine/widget-slash-menu/src/index.ts b/blocksuite/affine/widget-slash-menu/src/index.ts new file mode 100644 index 0000000000..ee66a3329d --- /dev/null +++ b/blocksuite/affine/widget-slash-menu/src/index.ts @@ -0,0 +1,3 @@ +// TODO(@L-Sun): narrow the scope of the exported symbols +export * from './extensions'; +export * from './widget'; diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/slash-menu-popover.ts b/blocksuite/affine/widget-slash-menu/src/slash-menu-popover.ts similarity index 99% rename from blocksuite/affine/block-root/src/widgets/slash-menu/slash-menu-popover.ts rename to blocksuite/affine/widget-slash-menu/src/slash-menu-popover.ts index f0a30ff68f..974d500122 100644 --- a/blocksuite/affine/block-root/src/widgets/slash-menu/slash-menu-popover.ts +++ b/blocksuite/affine/widget-slash-menu/src/slash-menu-popover.ts @@ -9,6 +9,7 @@ import { import { createKeydownObserver, getCurrentNativeRange, + getPopperPosition, isControlledKeyboardEvent, isFuzzyMatch, substringMatchScore, @@ -21,7 +22,6 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import { styleMap } from 'lit/directives/style-map.js'; import throttle from 'lodash-es/throttle'; -import { getPopperPosition } from '../../utils/position.js'; import type { SlashMenuActionItem, SlashMenuContext, @@ -147,7 +147,7 @@ export class SlashMenu extends WithDisposable(LitElement) { } get host() { - return this.context.rootComponent.host; + return this.context.std.host; } constructor( @@ -480,7 +480,7 @@ export class InnerSlashMenu extends WithDisposable(LitElement) { }); const inlineEditor = getInlineEditorByModel( - this.context.rootComponent.host, + this.context.std.host, this.context.model ); diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/styles.ts b/blocksuite/affine/widget-slash-menu/src/styles.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/styles.ts rename to blocksuite/affine/widget-slash-menu/src/styles.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/attachment.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/attachment.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/attachment.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/attachment.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/bold-text.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/bold-text.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/bold-text.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/bold-text.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/bulleted-list.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/bulleted-list.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/bulleted-list.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/bulleted-list.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/code-block.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/code-block.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/code-block.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/code-block.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/copy.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/copy.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/copy.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/copy.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/delete.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/delete.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/delete.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/delete.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/divider.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/divider.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/divider.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/divider.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/edgeless.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/edgeless.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/edgeless.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/edgeless.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/empty.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/empty.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/empty.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/empty.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/figma.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/figma.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/figma.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/figma.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/github-repo.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/github-repo.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/github-repo.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/github-repo.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-1.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/heading-1.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-1.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/heading-1.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-2.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/heading-2.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-2.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/heading-2.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-3.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/heading-3.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-3.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/heading-3.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-4.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/heading-4.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-4.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/heading-4.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-5.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/heading-5.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-5.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/heading-5.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-6.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/heading-6.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/heading-6.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/heading-6.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/index.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/index.ts similarity index 62% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/index.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/index.ts index c1b7e795e4..3231dce4a3 100644 --- a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/index.ts +++ b/blocksuite/affine/widget-slash-menu/src/tooltips/index.ts @@ -1,44 +1,44 @@ import type { TemplateResult } from 'lit'; -import { AttachmentTooltip } from './attachment.js'; -import { BoldTextTooltip } from './bold-text.js'; -import { BulletedListTooltip } from './bulleted-list.js'; -import { CodeBlockTooltip } from './code-block.js'; -import { CopyTooltip } from './copy.js'; -import { DeleteTooltip } from './delete.js'; -import { DividerTooltip } from './divider.js'; -import { EdgelessTooltip } from './edgeless.js'; -import { FigmaTooltip } from './figma.js'; -import { GithubRepoTooltip } from './github-repo.js'; -import { Heading1Tooltip } from './heading-1.js'; -import { Heading2Tooltip } from './heading-2.js'; -import { Heading3Tooltip } from './heading-3.js'; -import { Heading4Tooltip } from './heading-4.js'; -import { Heading5Tooltip } from './heading-5.js'; -import { Heading6Tooltip } from './heading-6.js'; -import { ItalicTooltip } from './italic.js'; -import { KanbanViewTooltip } from './kanban-view.js'; -import { LinearTooltip } from './linear.js'; -import { LinkTooltip } from './link.js'; -import { LinkDocTooltip } from './link-doc.js'; -import { MoveDownTooltip } from './move-down.js'; -import { MoveUpTooltip } from './move-up.js'; -import { NewDocTooltip } from './new-doc.js'; -import { NowTooltip } from './now.js'; -import { NumberedListTooltip } from './numbered-list.js'; -import { PDFTooltip } from './pdf.js'; -import { PhotoTooltip } from './photo.js'; -import { QuoteTooltip } from './quote.js'; -import { StrikethroughTooltip } from './strikethrough.js'; -import { TableViewTooltip } from './table-view.js'; -import { TextTooltip } from './text.js'; -import { ToDoListTooltip } from './to-do-list.js'; -import { TodayTooltip } from './today.js'; -import { TomorrowTooltip } from './tomorrow.js'; -import { TweetTooltip } from './tweet.js'; -import { UnderlineTooltip } from './underline.js'; -import { YesterdayTooltip } from './yesterday.js'; -import { YoutubeVideoTooltip } from './youtube-video.js'; +import { AttachmentTooltip } from './attachment'; +import { BoldTextTooltip } from './bold-text'; +import { BulletedListTooltip } from './bulleted-list'; +import { CodeBlockTooltip } from './code-block'; +import { CopyTooltip } from './copy'; +import { DeleteTooltip } from './delete'; +import { DividerTooltip } from './divider'; +import { EdgelessTooltip } from './edgeless'; +import { FigmaTooltip } from './figma'; +import { GithubRepoTooltip } from './github-repo'; +import { Heading1Tooltip } from './heading-1'; +import { Heading2Tooltip } from './heading-2'; +import { Heading3Tooltip } from './heading-3'; +import { Heading4Tooltip } from './heading-4'; +import { Heading5Tooltip } from './heading-5'; +import { Heading6Tooltip } from './heading-6'; +import { ItalicTooltip } from './italic'; +import { KanbanViewTooltip } from './kanban-view'; +import { LinearTooltip } from './linear'; +import { LinkTooltip } from './link'; +import { LinkDocTooltip } from './link-doc'; +import { MoveDownTooltip } from './move-down'; +import { MoveUpTooltip } from './move-up'; +import { NewDocTooltip } from './new-doc'; +import { NowTooltip } from './now'; +import { NumberedListTooltip } from './numbered-list'; +import { PDFTooltip } from './pdf'; +import { PhotoTooltip } from './photo'; +import { QuoteTooltip } from './quote'; +import { StrikethroughTooltip } from './strikethrough'; +import { TableViewTooltip } from './table-view'; +import { TextTooltip } from './text'; +import { ToDoListTooltip } from './to-do-list'; +import { TodayTooltip } from './today'; +import { TomorrowTooltip } from './tomorrow'; +import { TweetTooltip } from './tweet'; +import { UnderlineTooltip } from './underline'; +import { YesterdayTooltip } from './yesterday'; +import { YoutubeVideoTooltip } from './youtube-video'; export type SlashMenuTooltip = { figure: TemplateResult; diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/italic.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/italic.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/italic.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/italic.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/kanban-view.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/kanban-view.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/kanban-view.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/kanban-view.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/linear.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/linear.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/linear.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/linear.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/link-doc.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/link-doc.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/link-doc.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/link-doc.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/link.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/link.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/link.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/link.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/move-down.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/move-down.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/move-down.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/move-down.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/move-up.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/move-up.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/move-up.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/move-up.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/new-doc.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/new-doc.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/new-doc.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/new-doc.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/now.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/now.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/now.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/now.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/numbered-list.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/numbered-list.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/numbered-list.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/numbered-list.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/pdf.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/pdf.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/pdf.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/pdf.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/photo.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/photo.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/photo.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/photo.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/quote.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/quote.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/quote.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/quote.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/strikethrough.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/strikethrough.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/strikethrough.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/strikethrough.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/table-view.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/table-view.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/table-view.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/table-view.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/text.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/text.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/text.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/text.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/to-do-list.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/to-do-list.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/to-do-list.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/to-do-list.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/today.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/today.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/today.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/today.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/tomorrow.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/tomorrow.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/tomorrow.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/tomorrow.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/tweet.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/tweet.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/tweet.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/tweet.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/underline.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/underline.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/underline.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/underline.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/yesterday.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/yesterday.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/yesterday.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/yesterday.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/youtube-video.ts b/blocksuite/affine/widget-slash-menu/src/tooltips/youtube-video.ts similarity index 100% rename from blocksuite/affine/block-root/src/widgets/slash-menu/tooltips/youtube-video.ts rename to blocksuite/affine/widget-slash-menu/src/tooltips/youtube-video.ts diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/utils.ts b/blocksuite/affine/widget-slash-menu/src/utils.ts similarity index 81% rename from blocksuite/affine/block-root/src/widgets/slash-menu/utils.ts rename to blocksuite/affine/widget-slash-menu/src/utils.ts index 76d1791d5e..6988d68960 100644 --- a/blocksuite/affine/block-root/src/widgets/slash-menu/utils.ts +++ b/blocksuite/affine/widget-slash-menu/src/utils.ts @@ -103,8 +103,8 @@ export function createConversionItem( icon, tooltip: slashMenuToolTips[name], showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has(flavour), - action: ({ rootComponent }) => { - rootComponent.std.command.exec(updateBlockType, { + action: ({ std }) => { + std.command.exec(updateBlockType, { flavour, props: { type }, }); @@ -120,8 +120,8 @@ export function createTextFormatItem( name, icon, tooltip: slashMenuToolTips[name], - action: ({ rootComponent, model }) => { - const { std, host } = rootComponent; + action: ({ std, model }) => { + const { host } = std; if (model.text?.length !== 0) { std.command.exec(formatBlockCommand, { @@ -139,3 +139,22 @@ export function createTextFormatItem( }, }; } + +export function formatDate(date: Date) { + // yyyy-mm-dd + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, '0'); + const day = date.getDate().toString().padStart(2, '0'); + const strTime = `${year}-${month}-${day}`; + return strTime; +} + +export function formatTime(date: Date) { + // mm-dd hh:mm + const month = (date.getMonth() + 1).toString().padStart(2, '0'); + const day = date.getDate().toString().padStart(2, '0'); + const hours = date.getHours().toString().padStart(2, '0'); + const minutes = date.getMinutes().toString().padStart(2, '0'); + const strTime = `${month}-${day} ${hours}:${minutes}`; + return strTime; +} diff --git a/blocksuite/affine/block-root/src/widgets/slash-menu/index.ts b/blocksuite/affine/widget-slash-menu/src/widget.ts similarity index 91% rename from blocksuite/affine/block-root/src/widgets/slash-menu/index.ts rename to blocksuite/affine/widget-slash-menu/src/widget.ts index 296cb1a257..360b3a6bb9 100644 --- a/blocksuite/affine/block-root/src/widgets/slash-menu/index.ts +++ b/blocksuite/affine/widget-slash-menu/src/widget.ts @@ -5,11 +5,9 @@ import { import type { UIEventStateContext } from '@blocksuite/block-std'; import { TextSelection, WidgetComponent } from '@blocksuite/block-std'; import { DisposableGroup } from '@blocksuite/global/slot'; -import { assertType } from '@blocksuite/global/utils'; import { InlineEditor } from '@blocksuite/inline'; import debounce from 'lodash-es/debounce'; -import type { RootBlockComponent } from '../../types.js'; import { defaultSlashMenuConfig, type SlashMenuActionItem, @@ -19,9 +17,9 @@ import { type SlashMenuItemGenerator, type SlashMenuStaticConfig, type SlashSubMenu, -} from './config.js'; -import { SlashMenu } from './slash-menu-popover.js'; -import { filterEnabledSlashMenuItems } from './utils.js'; +} from './config'; +import { SlashMenu } from './slash-menu-popover'; +import { filterEnabledSlashMenuItems } from './utils'; export type AffineSlashMenuContext = SlashMenuContext; export type AffineSlashMenuItem = SlashMenuItem; @@ -57,7 +55,7 @@ const showSlashMenu = debounce( ); const inlineEditor = getInlineEditorByModel( - context.rootComponent.host, + context.std.host, context.model ); if (!inlineEditor) return; @@ -115,12 +113,10 @@ export class AffineSlashMenuWidget extends WidgetComponent { else inlineEditor.slots.inlineRangeSync.once(callback); }; - const rootComponent = this.block; - if (rootComponent.model.flavour !== 'affine:page') { + if (this.block.model.flavour !== 'affine:page') { console.error('SlashMenuWidget should be used in RootBlock'); return; } - assertType(rootComponent); inlineRangeApplyCallback(() => { const textSelection = this.host.selection.find(TextSelection); @@ -155,7 +151,7 @@ export class AffineSlashMenuWidget extends WidgetComponent { ...this.config, items: filterEnabledSlashMenuItems(this.config.items, { model, - rootComponent, + std: this.std, }), }; @@ -163,7 +159,7 @@ export class AffineSlashMenuWidget extends WidgetComponent { showSlashMenu({ context: { model, - rootComponent, + std: this.std, }, triggerKey: matchedKey, config, @@ -224,9 +220,3 @@ export class AffineSlashMenuWidget extends WidgetComponent { this.handleEvent('compositionEnd', this._onCompositionEnd); } } - -declare global { - interface HTMLElementTagNameMap { - [AFFINE_SLASH_MENU_WIDGET]: AffineSlashMenuWidget; - } -} diff --git a/blocksuite/affine/widget-slash-menu/tsconfig.json b/blocksuite/affine/widget-slash-menu/tsconfig.json new file mode 100644 index 0000000000..8dd9ad7ba8 --- /dev/null +++ b/blocksuite/affine/widget-slash-menu/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo" + }, + "include": ["./src"], + "references": [ + { "path": "../block-attachment" }, + { "path": "../block-database" }, + { "path": "../block-embed" }, + { "path": "../block-image" }, + { "path": "../block-latex" }, + { "path": "../block-note" }, + { "path": "../block-surface" }, + { "path": "../block-surface-ref" }, + { "path": "../block-table" }, + { "path": "../components" }, + { "path": "../shared" }, + { "path": "../../framework/block-std" }, + { "path": "../data-view" }, + { "path": "../../framework/global" }, + { "path": "../../framework/inline" }, + { "path": "../../framework/store" } + ] +} diff --git a/blocksuite/blocks/package.json b/blocksuite/blocks/package.json index c7b3c6f761..f5aef6814c 100644 --- a/blocksuite/blocks/package.json +++ b/blocksuite/blocks/package.json @@ -43,6 +43,7 @@ "@blocksuite/affine-widget-frame-title": "workspace:*", "@blocksuite/affine-widget-remote-selection": "workspace:*", "@blocksuite/affine-widget-scroll-anchoring": "workspace:*", + "@blocksuite/affine-widget-slash-menu": "workspace:*", "@blocksuite/affine-widget-toolbar": "workspace:*", "@blocksuite/block-std": "workspace:*", "@blocksuite/data-view": "workspace:*", diff --git a/blocksuite/blocks/src/effects.ts b/blocksuite/blocks/src/effects.ts index 3940d7be2d..d66f7c782b 100644 --- a/blocksuite/blocks/src/effects.ts +++ b/blocksuite/blocks/src/effects.ts @@ -46,6 +46,7 @@ import { effects as widgetEdgelessAutoConnectEffects } from '@blocksuite/affine- import { effects as widgetFrameTitleEffects } from '@blocksuite/affine-widget-frame-title/effects'; import { effects as widgetRemoteSelectionEffects } from '@blocksuite/affine-widget-remote-selection/effects'; import { effects as widgetScrollAnchoringEffects } from '@blocksuite/affine-widget-scroll-anchoring/effects'; +import { effects as widgetSlashMenuEffects } from '@blocksuite/affine-widget-slash-menu/effects'; import { effects as widgetToolbarEffects } from '@blocksuite/affine-widget-toolbar/effects'; import { effects as stdEffects } from '@blocksuite/block-std/effects'; import { effects as dataViewEffects } from '@blocksuite/data-view/effects'; @@ -103,6 +104,7 @@ export function effects() { widgetRemoteSelectionEffects(); widgetDragHandleEffects(); widgetEdgelessAutoConnectEffects(); + widgetSlashMenuEffects(); widgetToolbarEffects(); fragmentFramePanelEffects(); diff --git a/blocksuite/blocks/src/index.ts b/blocksuite/blocks/src/index.ts index d1188b4994..f6fb5fc27b 100644 --- a/blocksuite/blocks/src/index.ts +++ b/blocksuite/blocks/src/index.ts @@ -114,6 +114,9 @@ export { export type { DragBlockPayload } from '@blocksuite/affine-widget-drag-handle'; export { toolbarWidget } from '@blocksuite/affine-widget-toolbar'; +// TODO(@L-Sun): Narrow the export scope +export * from '@blocksuite/affine-widget-slash-menu'; + const env: Record = typeof globalThis !== 'undefined' ? globalThis diff --git a/blocksuite/blocks/tsconfig.json b/blocksuite/blocks/tsconfig.json index 141c89065e..b8fa9e5034 100644 --- a/blocksuite/blocks/tsconfig.json +++ b/blocksuite/blocks/tsconfig.json @@ -36,6 +36,7 @@ { "path": "../affine/widget-frame-title" }, { "path": "../affine/widget-remote-selection" }, { "path": "../affine/widget-scroll-anchoring" }, + { "path": "../affine/widget-slash-menu" }, { "path": "../affine/widget-toolbar" }, { "path": "../framework/block-std" }, { "path": "../affine/data-view" }, diff --git a/packages/frontend/core/src/blocksuite/ai/entries/slash-menu/setup-slash-menu.ts b/packages/frontend/core/src/blocksuite/ai/entries/slash-menu/setup-slash-menu.ts index 987146f846..812b986dc0 100644 --- a/packages/frontend/core/src/blocksuite/ai/entries/slash-menu/setup-slash-menu.ts +++ b/packages/frontend/core/src/blocksuite/ai/entries/slash-menu/setup-slash-menu.ts @@ -29,26 +29,28 @@ export function setupSlashMenuAIEntry(slashMenu: AffineSlashMenuWidget) { const showWhenWrapper = (item?: AIItemConfig) => - ({ rootComponent }: AffineSlashMenuContext) => { - const affineAIPanelWidget = rootComponent.host.view.getWidget( + ({ std }: AffineSlashMenuContext) => { + const root = std.host.doc.root; + if (!root) return false; + const affineAIPanelWidget = std.view.getWidget( AFFINE_AI_PANEL_WIDGET, - rootComponent.model.id + root.id ); if (affineAIPanelWidget === null) return false; - const chain = rootComponent.host.command.chain(); - const docModeService = rootComponent.std.get(DocModeProvider); - const editorMode = docModeService.getPrimaryMode(rootComponent.doc.id); + const chain = std.host.command.chain(); + const docModeService = std.get(DocModeProvider); + const editorMode = docModeService.getPrimaryMode(std.host.doc.id); - return item?.showWhen?.(chain, editorMode, rootComponent.host) ?? true; + return item?.showWhen?.(chain, editorMode, std.host) ?? true; }; const actionItemWrapper = ( item: AIItemConfig ): AffineSlashMenuActionItem => ({ ...basicItemConfig(item), - action: ({ rootComponent }: AffineSlashMenuContext) => { - item?.handler?.(rootComponent.host); + action: ({ std }: AffineSlashMenuContext) => { + item?.handler?.(std.host); }, }); @@ -58,7 +60,7 @@ export function setupSlashMenuAIEntry(slashMenu: AffineSlashMenuWidget) { subMenu: (item.subItem ?? []).map( ({ type, handler }) => ({ name: type, - action: ({ rootComponent }) => handler?.(rootComponent.host), + action: ({ std }) => handler?.(std.host), }) ), }; @@ -78,11 +80,12 @@ export function setupSlashMenuAIEntry(slashMenu: AffineSlashMenuWidget) { name: 'Ask AI', icon: AIStarIcon, showWhen: showWhenWrapper(), - action: ({ rootComponent }) => { - const view = rootComponent.host.view; - const affineAIPanelWidget = view.getWidget( + action: ({ std }) => { + const root = std.host.doc.root; + if (!root) return; + const affineAIPanelWidget = std.view.getWidget( AFFINE_AI_PANEL_WIDGET, - rootComponent.model.id + root.id ) as AffineAIPanelWidget; handleInlineAskAIAction(affineAIPanelWidget.host); }, diff --git a/packages/frontend/core/src/blocksuite/extensions/entry/enable-mobile.ts b/packages/frontend/core/src/blocksuite/extensions/entry/enable-mobile.ts index da593cb029..4b6df32a2e 100644 --- a/packages/frontend/core/src/blocksuite/extensions/entry/enable-mobile.ts +++ b/packages/frontend/core/src/blocksuite/extensions/entry/enable-mobile.ts @@ -17,7 +17,7 @@ import { imageToolbarWidget, ParagraphBlockService, ReferenceNodeConfigIdentifier, - slashMenuWidget, + SlashMenuExtension, surfaceRefToolbarWidget, toolbarWidget, VirtualKeyboardProvider as BSVirtualKeyboardProvider, @@ -166,10 +166,10 @@ export function enableMobileExtension( specBuilder: SpecBuilder, framework: FrameworkProvider ): void { - specBuilder.omit(slashMenuWidget); specBuilder.omit(codeToolbarWidget); specBuilder.omit(imageToolbarWidget); specBuilder.omit(surfaceRefToolbarWidget); specBuilder.omit(toolbarWidget); + specBuilder.omit(SlashMenuExtension); specBuilder.extend([MobileSpecsPatches, KeyboardToolbarExtension(framework)]); } diff --git a/packages/frontend/core/src/blocksuite/extensions/quick-search-service.ts b/packages/frontend/core/src/blocksuite/extensions/quick-search-service.ts index 2bd93d541d..54eb1f74e4 100644 --- a/packages/frontend/core/src/blocksuite/extensions/quick-search-service.ts +++ b/packages/frontend/core/src/blocksuite/extensions/quick-search-service.ts @@ -137,11 +137,10 @@ export function patchQuickSearchService(framework: FrameworkProvider) { 'action' in item && (item.name === 'Linked Doc' || item.name === 'Link') ) { - item.action = async ({ rootComponent }) => { - const [success, { insertedLinkType }] = - rootComponent.std.command.exec( - insertLinkByQuickSearchCommand - ); + item.action = async ({ std }) => { + const [success, { insertedLinkType }] = std.command.exec( + insertLinkByQuickSearchCommand + ); if (!success) return; diff --git a/tools/utils/src/workspace.gen.ts b/tools/utils/src/workspace.gen.ts index e16cd6e209..c6971faad3 100644 --- a/tools/utils/src/workspace.gen.ts +++ b/tools/utils/src/workspace.gen.ts @@ -250,6 +250,7 @@ export const PackageList = [ 'blocksuite/affine/widget-frame-title', 'blocksuite/affine/widget-remote-selection', 'blocksuite/affine/widget-scroll-anchoring', + 'blocksuite/affine/widget-slash-menu', 'blocksuite/affine/widget-toolbar', 'blocksuite/framework/block-std', 'blocksuite/affine/data-view', @@ -435,6 +436,28 @@ export const PackageList = [ 'blocksuite/framework/global', ], }, + { + location: 'blocksuite/affine/widget-slash-menu', + name: '@blocksuite/affine-widget-slash-menu', + workspaceDependencies: [ + 'blocksuite/affine/block-attachment', + 'blocksuite/affine/block-database', + 'blocksuite/affine/block-embed', + 'blocksuite/affine/block-image', + 'blocksuite/affine/block-latex', + 'blocksuite/affine/block-note', + 'blocksuite/affine/block-surface', + 'blocksuite/affine/block-surface-ref', + 'blocksuite/affine/block-table', + 'blocksuite/affine/components', + 'blocksuite/affine/shared', + 'blocksuite/framework/block-std', + 'blocksuite/affine/data-view', + 'blocksuite/framework/global', + 'blocksuite/framework/inline', + 'blocksuite/framework/store', + ], + }, { location: 'blocksuite/affine/widget-toolbar', name: '@blocksuite/affine-widget-toolbar', @@ -481,6 +504,7 @@ export const PackageList = [ 'blocksuite/affine/widget-frame-title', 'blocksuite/affine/widget-remote-selection', 'blocksuite/affine/widget-scroll-anchoring', + 'blocksuite/affine/widget-slash-menu', 'blocksuite/affine/widget-toolbar', 'blocksuite/framework/block-std', 'blocksuite/affine/data-view', @@ -887,6 +911,7 @@ export type PackageName = | '@blocksuite/affine-widget-frame-title' | '@blocksuite/affine-widget-remote-selection' | '@blocksuite/affine-widget-scroll-anchoring' + | '@blocksuite/affine-widget-slash-menu' | '@blocksuite/affine-widget-toolbar' | '@blocksuite/blocks' | '@blocksuite/block-std' diff --git a/tsconfig.json b/tsconfig.json index 338813c479..1dc038e9d1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -81,6 +81,7 @@ { "path": "./blocksuite/affine/widget-frame-title" }, { "path": "./blocksuite/affine/widget-remote-selection" }, { "path": "./blocksuite/affine/widget-scroll-anchoring" }, + { "path": "./blocksuite/affine/widget-slash-menu" }, { "path": "./blocksuite/affine/widget-toolbar" }, { "path": "./blocksuite/blocks" }, { "path": "./blocksuite/framework/block-std" }, diff --git a/yarn.lock b/yarn.lock index 9268e0edac..1b5e7c6beb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2608,6 +2608,7 @@ __metadata: "@blocksuite/affine-widget-frame-title": "workspace:*" "@blocksuite/affine-widget-remote-selection": "workspace:*" "@blocksuite/affine-widget-scroll-anchoring": "workspace:*" + "@blocksuite/affine-widget-slash-menu": "workspace:*" "@blocksuite/affine-widget-toolbar": "workspace:*" "@blocksuite/block-std": "workspace:*" "@blocksuite/data-view": "workspace:*" @@ -2948,6 +2949,36 @@ __metadata: languageName: unknown linkType: soft +"@blocksuite/affine-widget-slash-menu@workspace:*, @blocksuite/affine-widget-slash-menu@workspace:blocksuite/affine/widget-slash-menu": + version: 0.0.0-use.local + resolution: "@blocksuite/affine-widget-slash-menu@workspace:blocksuite/affine/widget-slash-menu" + dependencies: + "@blocksuite/affine-block-attachment": "workspace:*" + "@blocksuite/affine-block-database": "workspace:*" + "@blocksuite/affine-block-embed": "workspace:*" + "@blocksuite/affine-block-image": "workspace:*" + "@blocksuite/affine-block-latex": "workspace:*" + "@blocksuite/affine-block-note": "workspace:*" + "@blocksuite/affine-block-surface": "workspace:*" + "@blocksuite/affine-block-surface-ref": "workspace:*" + "@blocksuite/affine-block-table": "workspace:*" + "@blocksuite/affine-components": "workspace:*" + "@blocksuite/affine-shared": "workspace:*" + "@blocksuite/block-std": "workspace:*" + "@blocksuite/data-view": "workspace:*" + "@blocksuite/global": "workspace:*" + "@blocksuite/icons": "npm:^2.2.4" + "@blocksuite/inline": "workspace:*" + "@blocksuite/store": "workspace:*" + "@floating-ui/dom": "npm:^1.6.13" + "@preact/signals-core": "npm:^1.8.0" + "@toeverything/theme": "npm:^1.1.12" + "@types/lodash-es": "npm:^4.17.12" + lit: "npm:^3.2.0" + lodash-es: "npm:^4.17.21" + languageName: unknown + linkType: soft + "@blocksuite/affine-widget-toolbar@workspace:*, @blocksuite/affine-widget-toolbar@workspace:blocksuite/affine/widget-toolbar": version: 0.0.0-use.local resolution: "@blocksuite/affine-widget-toolbar@workspace:blocksuite/affine/widget-toolbar" @@ -3049,6 +3080,7 @@ __metadata: "@blocksuite/affine-widget-frame-title": "workspace:*" "@blocksuite/affine-widget-remote-selection": "workspace:*" "@blocksuite/affine-widget-scroll-anchoring": "workspace:*" + "@blocksuite/affine-widget-slash-menu": "workspace:*" "@blocksuite/affine-widget-toolbar": "workspace:*" "@blocksuite/block-std": "workspace:*" "@blocksuite/data-view": "workspace:*" @@ -3097,7 +3129,7 @@ __metadata: languageName: unknown linkType: soft -"@blocksuite/icons@npm:2.2.4, @blocksuite/icons@npm:^2.2.1, @blocksuite/icons@npm:^2.2.2, @blocksuite/icons@npm:^2.2.3": +"@blocksuite/icons@npm:2.2.4, @blocksuite/icons@npm:^2.2.1, @blocksuite/icons@npm:^2.2.2, @blocksuite/icons@npm:^2.2.3, @blocksuite/icons@npm:^2.2.4": version: 2.2.4 resolution: "@blocksuite/icons@npm:2.2.4" peerDependencies: