refactor(editor): extract attachment block (#9308)

This commit is contained in:
Saul-Mirone
2024-12-25 12:19:58 +00:00
parent d8bc145465
commit ebd97752bf
35 changed files with 272 additions and 125 deletions

View File

@@ -0,0 +1,44 @@
{
"name": "@blocksuite/affine-block-attachment",
"description": "Attachment block for BlockSuite.",
"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-embed": "workspace:*",
"@blocksuite/affine-components": "workspace:*",
"@blocksuite/affine-model": "workspace:*",
"@blocksuite/affine-shared": "workspace:*",
"@blocksuite/block-std": "workspace:*",
"@blocksuite/global": "workspace:*",
"@blocksuite/icons": "^2.1.75",
"@blocksuite/inline": "workspace:*",
"@blocksuite/store": "workspace:*",
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.1",
"file-type": "^19.5.0",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
"zod": "^3.23.8"
},
"exports": {
".": "./src/index.ts",
"./effects": "./src/effects.ts"
},
"files": [
"src",
"dist",
"!src/__tests__",
"!dist/__tests__"
]
}

View File

@@ -4,10 +4,10 @@ import {
EMBED_CARD_HEIGHT,
EMBED_CARD_WIDTH,
} from '@blocksuite/affine-shared/consts';
import { toGfxBlockComponent } from '@blocksuite/block-std';
import { type BlockService, toGfxBlockComponent } from '@blocksuite/block-std';
import type { Slot } from '@blocksuite/store';
import { styleMap } from 'lit/directives/style-map.js';
import type { EdgelessRootService } from '../root-block/index.js';
import { AttachmentBlockComponent } from './attachment-block.js';
export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent(
@@ -17,15 +17,20 @@ export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent(
override blockDraggable = false;
get rootService() {
return this.std.getService('affine:page') as EdgelessRootService;
get rootService(): null | (BlockService & { slots: Record<string, Slot> }) {
return this.std.getService('affine:page');
}
override connectedCallback(): void {
super.connectedCallback();
const rootService = this.rootService;
if (!rootService) {
console.warn('rootService is not found');
return;
}
// TODO: move root service slots to extension
this._disposables.add(
rootService.slots.elementResizeStart.on(() => {
this._isResizing = true;
@@ -33,6 +38,7 @@ export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent(
})
);
// TODO: move root service slots to extension
this._disposables.add(
rootService.slots.elementResizeEnd.on(() => {
this._isResizing = false;

View File

@@ -8,8 +8,7 @@ import {
import { BlockService } from '@blocksuite/block-std';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { addAttachments } from '../root-block/edgeless/utils/common.js';
import { addSiblingAttachmentBlocks } from './utils.js';
import { addAttachments, addSiblingAttachmentBlocks } from './utils.js';
// bytes.parse('2GB')
const maxFileSize = 2147483648;
@@ -30,7 +29,10 @@ export const AttachmentDropOption = FileDropConfigExtension({
if (!attachmentFiles.length) return false;
if (targetModel && !matchFlavours(targetModel, ['affine:surface'])) {
if (
targetModel &&
!matchFlavours(targetModel, ['affine:surface' as BlockSuite.Flavour])
) {
addSiblingAttachmentBlocks(
std.host,
attachmentFiles,

View File

@@ -0,0 +1,19 @@
import { AttachmentBlockComponent } from './attachment-block';
import { AttachmentEdgelessBlockComponent } from './attachment-edgeless-block';
import type { AttachmentBlockService } from './attachment-service';
export function effects() {
customElements.define(
'affine-edgeless-attachment',
AttachmentEdgelessBlockComponent
);
customElements.define('affine-attachment', AttachmentBlockComponent);
}
declare global {
namespace BlockSuite {
interface BlockServices {
'affine:attachment': AttachmentBlockService;
}
}
}

View File

@@ -0,0 +1,11 @@
export * from './adapters/notion-html';
export * from './attachment-block';
export * from './attachment-service';
export * from './attachment-spec';
export { attachmentViewToggleMenu } from './components/options';
export {
type AttachmentEmbedConfig,
AttachmentEmbedConfigIdentifier,
AttachmentEmbedProvider,
} from './embed';
export { addAttachments, addSiblingAttachmentBlocks } from './utils';

View File

@@ -4,9 +4,15 @@ import type {
AttachmentBlockProps,
} from '@blocksuite/affine-model';
import { defaultAttachmentProps } from '@blocksuite/affine-model';
import {
EMBED_CARD_HEIGHT,
EMBED_CARD_WIDTH,
} from '@blocksuite/affine-shared/consts';
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
import { humanFileSize } from '@blocksuite/affine-shared/utils';
import type { EditorHost } from '@blocksuite/block-std';
import type { BlockStdScope, EditorHost } from '@blocksuite/block-std';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { Bound, type IVec, Point, Vec } from '@blocksuite/global/utils';
import type { BlockModel } from '@blocksuite/store';
import type { AttachmentBlockComponent } from './attachment-block.js';
@@ -251,3 +257,80 @@ export async function addSiblingAttachmentBlocks(
return blockIds;
}
export async function addAttachments(
std: BlockStdScope,
files: File[],
point?: IVec
): Promise<string[]> {
if (!files.length) return [];
const attachmentService = std.getService('affine:attachment');
const gfx = std.get(GfxControllerIdentifier);
if (!attachmentService) {
console.error('Attachment service not found');
return [];
}
const maxFileSize = attachmentService.maxFileSize;
const isSizeExceeded = files.some(file => file.size > maxFileSize);
if (isSizeExceeded) {
toast(
std.host,
`You can only upload files less than ${humanFileSize(
maxFileSize,
true,
0
)}`
);
return [];
}
let { x, y } = gfx.viewport.center;
if (point) [x, y] = gfx.viewport.toModelCoord(...point);
const CARD_STACK_GAP = 32;
const dropInfos: { blockId: string; file: File }[] = files.map(
(file, index) => {
const point = new Point(
x + index * CARD_STACK_GAP,
y + index * CARD_STACK_GAP
);
const center = Vec.toVec(point);
const bound = Bound.fromCenter(
center,
EMBED_CARD_WIDTH.cubeThick,
EMBED_CARD_HEIGHT.cubeThick
);
const blockId = std.doc.addBlock(
'affine:attachment',
{
name: file.name,
size: file.size,
type: file.type,
style: 'cubeThick',
xywh: bound.serialize(),
} satisfies Partial<AttachmentBlockProps>,
gfx.surface
);
return { blockId, file };
}
);
// upload file and update the attachment model
const uploadPromises = dropInfos.map(async ({ blockId, file }) => {
const filetype = await getFileType(file);
await uploadAttachmentBlob(std.host, blockId, file, filetype, true);
return blockId;
});
const blockIds = await Promise.all(uploadPromises);
gfx.selection.set({
elements: blockIds,
editing: false,
});
return blockIds;
}

View File

@@ -0,0 +1,35 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src/",
"outDir": "./dist/",
"noEmit": false
},
"include": ["./src"],
"references": [
{
"path": "../../framework/global"
},
{
"path": "../../framework/store"
},
{
"path": "../../framework/block-std"
},
{
"path": "../../framework/inline"
},
{
"path": "../model"
},
{
"path": "../components"
},
{
"path": "../shared"
},
{
"path": "../block-embed"
}
]
}

View File

@@ -14,6 +14,7 @@
"author": "toeverything",
"license": "MIT",
"dependencies": {
"@blocksuite/affine-block-attachment": "workspace:*",
"@blocksuite/affine-block-bookmark": "workspace:*",
"@blocksuite/affine-block-embed": "workspace:*",
"@blocksuite/affine-block-list": "workspace:*",

View File

@@ -1,3 +1,4 @@
import { attachmentBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-attachment';
import { bookmarkBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-bookmark';
import {
embedFigmaBlockNotionHtmlAdapterMatcher,
@@ -9,7 +10,6 @@ import { listBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-list
import { paragraphBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-paragraph';
import type { BlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-shared/adapters';
import { attachmentBlockNotionHtmlAdapterMatcher } from '../../../attachment-block/adapters/notion-html.js';
import { codeBlockNotionHtmlAdapterMatcher } from '../../../code-block/adapters/notion-html.js';
import { databaseBlockNotionHtmlAdapterMatcher } from '../../../database-block/adapters/notion-html.js';
import { dividerBlockNotionHtmlAdapterMatcher } from '../../../divider-block/adapters/notion-html.js';

View File

@@ -1,3 +1,4 @@
import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment';
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
import { EmbedExtensions } from '@blocksuite/affine-block-embed';
import { ListBlockSpec } from '@blocksuite/affine-block-list';
@@ -7,7 +8,6 @@ import { EditPropsStore } from '@blocksuite/affine-shared/services';
import type { ExtensionType } from '@blocksuite/block-std';
import { AdapterFactoryExtensions } from '../_common/adapters/extension.js';
import { AttachmentBlockSpec } from '../attachment-block/attachment-spec.js';
import { CodeBlockSpec } from '../code-block/code-block-spec.js';
import { DataViewBlockSpec } from '../data-view-block/data-view-spec.js';
import { DatabaseBlockSpec } from '../database-block/database-spec.js';

View File

@@ -1,3 +1,4 @@
import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment';
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
import {
EmbedFigmaBlockSpec,
@@ -11,7 +12,6 @@ import {
import { ListBlockSpec } from '@blocksuite/affine-block-list';
import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph';
import { AttachmentBlockSpec } from '../../attachment-block/attachment-spec.js';
import { CodeBlockSpec } from '../../code-block/code-block-spec.js';
import { DataViewBlockSpec } from '../../data-view-block/data-view-spec.js';
import { DatabaseBlockSpec } from '../../database-block/database-spec.js';

View File

@@ -1,8 +0,0 @@
export * from './attachment-block.js';
export * from './attachment-service.js';
export { attachmentViewToggleMenu } from './components/options.js';
export {
type AttachmentEmbedConfig,
AttachmentEmbedConfigIdentifier,
AttachmentEmbedProvider,
} from './embed.js';

View File

@@ -1,3 +1,4 @@
import { effects as blockAttachmentEffects } from '@blocksuite/affine-block-attachment/effects';
import { effects as blockBookmarkEffects } from '@blocksuite/affine-block-bookmark/effects';
import { effects as blockEmbedEffects } from '@blocksuite/affine-block-embed/effects';
import { effects as blockListEffects } from '@blocksuite/affine-block-list/effects';
@@ -29,11 +30,6 @@ import { EmbedCardEditCaptionEditModal } from './_common/components/embed-card/m
import { EmbedCardCreateModal } from './_common/components/embed-card/modal/embed-card-create-modal.js';
import { EmbedCardEditModal } from './_common/components/embed-card/modal/embed-card-edit-modal.js';
import { registerSpecs } from './_specs/register-specs.js';
import { AttachmentEdgelessBlockComponent } from './attachment-block/attachment-edgeless-block.js';
import {
AttachmentBlockComponent,
type AttachmentBlockService,
} from './attachment-block/index.js';
import { AffineCodeUnit } from './code-block/highlight/affine-code-unit.js';
import {
CodeBlockComponent,
@@ -275,6 +271,7 @@ export function effects() {
stdEffects();
inlineEffects();
blockAttachmentEffects();
blockBookmarkEffects();
blockListEffects();
blockParagraphEffects();
@@ -322,13 +319,8 @@ export function effects() {
);
customElements.define('affine-edgeless-text', EdgelessTextBlockComponent);
customElements.define('center-peek', CenterPeek);
customElements.define(
'affine-edgeless-attachment',
AttachmentEdgelessBlockComponent
);
customElements.define('database-datasource-note-renderer', NoteRenderer);
customElements.define('database-datasource-block-renderer', BlockRenderer);
customElements.define('affine-attachment', AttachmentBlockComponent);
customElements.define('affine-latex', LatexBlockComponent);
customElements.define('affine-page-root', PageRootBlockComponent);
customElements.define('edgeless-note-mask', EdgelessNoteMask);
@@ -594,7 +586,6 @@ declare global {
interface BlockServices {
'affine:note': NoteBlockService;
'affine:page': RootService;
'affine:attachment': AttachmentBlockService;
'affine:database': DatabaseBlockService;
'affine:image': ImageBlockService;
}

View File

@@ -16,7 +16,6 @@ export * from './_common/test-utils/test-utils.js';
export * from './_common/transformers/index.js';
export { type AbstractEditor } from './_common/types.js';
export * from './_specs/index.js';
export * from './attachment-block/index.js';
export * from './code-block/index.js';
export * from './data-view-block/index.js';
export * from './database-block/index.js';
@@ -49,6 +48,7 @@ export {
MiniMindmapPreview,
} from './surface-block/mini-mindmap/index.js';
export * from './surface-ref-block/index.js';
export * from '@blocksuite/affine-block-attachment';
export * from '@blocksuite/affine-block-bookmark';
export * from '@blocksuite/affine-block-embed';
export * from '@blocksuite/affine-block-list';

View File

@@ -1,3 +1,4 @@
import { addAttachments } from '@blocksuite/affine-block-attachment';
import {
CanvasElementType,
SurfaceGroupLikeModel,
@@ -75,7 +76,7 @@ import {
getSortedCloneElements,
serializeElement,
} from '../utils/clone-utils.js';
import { addAttachments, addImages } from '../utils/common.js';
import { addImages } from '../utils/common.js';
import { deleteElements } from '../utils/crud.js';
import {
isAttachmentBlock,

View File

@@ -1,3 +1,4 @@
import { addAttachments } from '@blocksuite/affine-block-attachment';
import { AttachmentIcon, LinkIcon } from '@blocksuite/affine-components/icons';
import { MAX_IMAGE_WIDTH } from '@blocksuite/affine-model';
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
@@ -14,7 +15,7 @@ import {
} from '../../../../../_common/utils/index.js';
import { ImageIcon } from '../../../../../image-block/styles.js';
import type { NoteToolOption } from '../../../gfx-tool/note-tool.js';
import { addAttachments, addImages } from '../../../utils/common.js';
import { addImages } from '../../../utils/common.js';
import { getTooltipWithShortcut } from '../../utils.js';
import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js';
import { NOTE_MENU_ITEMS } from './note-menu-config.js';

View File

@@ -1,7 +1,6 @@
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
import { toast } from '@blocksuite/affine-components/toast';
import {
type AttachmentBlockProps,
DEFAULT_NOTE_HEIGHT,
DEFAULT_NOTE_WIDTH,
type ImageBlockProps,
@@ -9,10 +8,6 @@ import {
type NoteBlockModel,
NoteDisplayMode,
} from '@blocksuite/affine-model';
import {
EMBED_CARD_HEIGHT,
EMBED_CARD_WIDTH,
} from '@blocksuite/affine-shared/consts';
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
import type { NoteChildrenFlavour } from '@blocksuite/affine-shared/types';
import {
@@ -22,7 +17,6 @@ import {
import type { BlockStdScope } from '@blocksuite/block-std';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import {
Bound,
type IPoint,
type IVec,
Point,
@@ -30,91 +24,10 @@ import {
Vec,
} from '@blocksuite/global/utils';
import {
getFileType,
uploadAttachmentBlob,
} from '../../../attachment-block/utils.js';
import { calcBoundByOrigin, readImageSize } from '../components/utils.js';
import { DEFAULT_NOTE_OFFSET_X, DEFAULT_NOTE_OFFSET_Y } from './consts.js';
import { addBlock } from './crud.js';
export async function addAttachments(
std: BlockStdScope,
files: File[],
point?: IVec
): Promise<string[]> {
if (!files.length) return [];
const attachmentService = std.getService('affine:attachment');
const gfx = std.get(GfxControllerIdentifier);
if (!attachmentService) {
console.error('Attachment service not found');
return [];
}
const maxFileSize = attachmentService.maxFileSize;
const isSizeExceeded = files.some(file => file.size > maxFileSize);
if (isSizeExceeded) {
toast(
std.host,
`You can only upload files less than ${humanFileSize(
maxFileSize,
true,
0
)}`
);
return [];
}
let { x, y } = gfx.viewport.center;
if (point) [x, y] = gfx.viewport.toModelCoord(...point);
const CARD_STACK_GAP = 32;
const dropInfos: { blockId: string; file: File }[] = files.map(
(file, index) => {
const point = new Point(
x + index * CARD_STACK_GAP,
y + index * CARD_STACK_GAP
);
const center = Vec.toVec(point);
const bound = Bound.fromCenter(
center,
EMBED_CARD_WIDTH.cubeThick,
EMBED_CARD_HEIGHT.cubeThick
);
const blockId = std.doc.addBlock(
'affine:attachment',
{
name: file.name,
size: file.size,
type: file.type,
style: 'cubeThick',
xywh: bound.serialize(),
} satisfies Partial<AttachmentBlockProps>,
gfx.surface
);
return { blockId, file };
}
);
// upload file and update the attachment model
const uploadPromises = dropInfos.map(async ({ blockId, file }) => {
const filetype = await getFileType(file);
await uploadAttachmentBlob(std.host, blockId, file, filetype, true);
return blockId;
});
const blockIds = await Promise.all(uploadPromises);
gfx.selection.set({
elements: blockIds,
editing: false,
});
return blockIds;
}
export async function addImages(
std: BlockStdScope,
files: File[],

View File

@@ -1,3 +1,7 @@
import {
type AttachmentBlockComponent,
attachmentViewToggleMenu,
} from '@blocksuite/affine-block-attachment';
import { getEmbedCardIcons } from '@blocksuite/affine-block-embed';
import {
CaptionIcon,
@@ -18,8 +22,6 @@ import { property } from 'lit/decorators.js';
import { join } from 'lit/directives/join.js';
import type { EmbedCardStyle } from '../../../_common/types.js';
import type { AttachmentBlockComponent } from '../../../attachment-block/index.js';
import { attachmentViewToggleMenu } from '../../../attachment-block/index.js';
import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js';
export class EdgelessChangeAttachmentButton extends WithDisposable(LitElement) {

View File

@@ -1,3 +1,4 @@
import type { AttachmentBlockComponent } from '@blocksuite/affine-block-attachment';
import type { BookmarkBlockComponent } from '@blocksuite/affine-block-bookmark';
import type {
EmbedFigmaBlockComponent,
@@ -31,7 +32,6 @@ import {
notifyDocCreated,
promptDocTitle,
} from '../../../../_common/utils/render-linked-doc.js';
import type { AttachmentBlockComponent } from '../../../../attachment-block/attachment-block.js';
import type { ImageBlockComponent } from '../../../../image-block/image-block.js';
import { duplicate } from '../../../edgeless/utils/clipboard-utils.js';
import { getSortedCloneElements } from '../../../edgeless/utils/clone-utils.js';

View File

@@ -1,3 +1,4 @@
import { addSiblingAttachmentBlocks } from '@blocksuite/affine-block-attachment';
import {
getInlineEditorByModel,
insertContent,
@@ -60,7 +61,6 @@ import { cssVarV2 } from '@toeverything/theme/v2';
import type { TemplateResult } from 'lit';
import { toggleEmbedCardCreateModal } from '../../../_common/components/embed-card/modal/embed-card-create-modal.js';
import { addSiblingAttachmentBlocks } from '../../../attachment-block/utils.js';
import { getSurfaceBlock } from '../../../surface-ref-block/utils.js';
import type { PageRootBlockComponent } from '../../page/page-root-block.js';
import { formatDate, formatTime } from '../../utils/misc.js';

View File

@@ -1,3 +1,4 @@
import { addSiblingAttachmentBlocks } from '@blocksuite/affine-block-attachment';
import {
FigmaIcon,
GithubIcon,
@@ -49,7 +50,6 @@ import type { TemplateResult } from 'lit';
import { toggleEmbedCardCreateModal } from '../../../_common/components/embed-card/modal/embed-card-create-modal.js';
import { textConversionConfigs } from '../../../_common/configs/text-conversion.js';
import { addSiblingAttachmentBlocks } from '../../../attachment-block/utils.js';
import type { DataViewBlockComponent } from '../../../data-view-block/index.js';
import { getSurfaceBlock } from '../../../surface-ref-block/utils.js';
import type { RootBlockComponent } from '../../types.js';

View File

@@ -40,6 +40,9 @@
{
"path": "../affine/block-bookmark"
},
{
"path": "../affine/block-attachment"
},
{
"path": "../affine/data-view"
},

View File

@@ -13,6 +13,20 @@ export const PackageList = [
'blocksuite/framework/store',
],
},
{
location: 'blocksuite/affine/block-attachment',
name: '@blocksuite/affine-block-attachment',
workspaceDependencies: [
'blocksuite/affine/block-embed',
'blocksuite/affine/components',
'blocksuite/affine/model',
'blocksuite/affine/shared',
'blocksuite/framework/block-std',
'blocksuite/framework/global',
'blocksuite/framework/inline',
'blocksuite/framework/store',
],
},
{
location: 'blocksuite/affine/block-bookmark',
name: '@blocksuite/affine-block-bookmark',
@@ -138,6 +152,7 @@ export const PackageList = [
location: 'blocksuite/blocks',
name: '@blocksuite/blocks',
workspaceDependencies: [
'blocksuite/affine/block-attachment',
'blocksuite/affine/block-bookmark',
'blocksuite/affine/block-embed',
'blocksuite/affine/block-list',
@@ -472,6 +487,7 @@ export const PackageList = [
export type PackageName =
| '@blocksuite/affine'
| '@blocksuite/affine-block-attachment'
| '@blocksuite/affine-block-bookmark'
| '@blocksuite/affine-block-embed'
| '@blocksuite/affine-block-list'

View File

@@ -7,6 +7,8 @@
"include": [],
"references": [
{ "path": "./blocksuite/affine/all" },
{ "path": "./blocksuite/affine/block-attachment" },
{ "path": "./blocksuite/affine/block-bookmark" },
{ "path": "./blocksuite/affine/block-embed" },
{ "path": "./blocksuite/affine/block-list" },
{ "path": "./blocksuite/affine/block-paragraph" },

View File

@@ -3224,6 +3224,30 @@ __metadata:
languageName: node
linkType: hard
"@blocksuite/affine-block-attachment@workspace:*, @blocksuite/affine-block-attachment@workspace:blocksuite/affine/block-attachment":
version: 0.0.0-use.local
resolution: "@blocksuite/affine-block-attachment@workspace:blocksuite/affine/block-attachment"
dependencies:
"@blocksuite/affine-block-embed": "workspace:*"
"@blocksuite/affine-components": "workspace:*"
"@blocksuite/affine-model": "workspace:*"
"@blocksuite/affine-shared": "workspace:*"
"@blocksuite/block-std": "workspace:*"
"@blocksuite/global": "workspace:*"
"@blocksuite/icons": "npm:^2.1.75"
"@blocksuite/inline": "workspace:*"
"@blocksuite/store": "workspace:*"
"@floating-ui/dom": "npm:^1.6.10"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
"@toeverything/theme": "npm:^1.1.1"
file-type: "npm:^19.5.0"
lit: "npm:^3.2.0"
minimatch: "npm:^10.0.1"
zod: "npm:^3.23.8"
languageName: unknown
linkType: soft
"@blocksuite/affine-block-bookmark@workspace:*, @blocksuite/affine-block-bookmark@workspace:blocksuite/affine/block-bookmark":
version: 0.0.0-use.local
resolution: "@blocksuite/affine-block-bookmark@workspace:blocksuite/affine/block-bookmark"
@@ -3458,6 +3482,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@blocksuite/blocks@workspace:blocksuite/blocks"
dependencies:
"@blocksuite/affine-block-attachment": "workspace:*"
"@blocksuite/affine-block-bookmark": "workspace:*"
"@blocksuite/affine-block-embed": "workspace:*"
"@blocksuite/affine-block-list": "workspace:*"