mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 14:27:02 +08:00
refactor(editor): extract note block (#9310)
This commit is contained in:
@@ -5,14 +5,18 @@ import {
|
|||||||
NoteDisplayMode,
|
NoteDisplayMode,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import { EMBED_CARD_HEIGHT } from '@blocksuite/affine-shared/consts';
|
import { EMBED_CARD_HEIGHT } from '@blocksuite/affine-shared/consts';
|
||||||
|
import { NotificationProvider } from '@blocksuite/affine-shared/services';
|
||||||
import { matchFlavours, SpecProvider } from '@blocksuite/affine-shared/utils';
|
import { matchFlavours, SpecProvider } from '@blocksuite/affine-shared/utils';
|
||||||
import { BlockStdScope } from '@blocksuite/block-std';
|
import { BlockStdScope } from '@blocksuite/block-std';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import {
|
import {
|
||||||
type BlockModel,
|
type BlockModel,
|
||||||
|
type BlockSnapshot,
|
||||||
BlockViewType,
|
BlockViewType,
|
||||||
type Doc,
|
type Doc,
|
||||||
|
type DraftModel,
|
||||||
type Query,
|
type Query,
|
||||||
|
Slice,
|
||||||
} from '@blocksuite/store';
|
} from '@blocksuite/store';
|
||||||
import { render, type TemplateResult } from 'lit';
|
import { render, type TemplateResult } from 'lit';
|
||||||
|
|
||||||
@@ -295,3 +299,122 @@ export function getDocContentWithMaxLength(doc: Doc, maxlength = 500) {
|
|||||||
|
|
||||||
return texts.join('\n');
|
return texts.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTitleFromSelectedModels(selectedModels: DraftModel[]) {
|
||||||
|
const firstBlock = selectedModels[0];
|
||||||
|
if (
|
||||||
|
matchFlavours(firstBlock, ['affine:paragraph']) &&
|
||||||
|
firstBlock.type.startsWith('h')
|
||||||
|
) {
|
||||||
|
return firstBlock.text.toString();
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function promptDocTitle(std: BlockStdScope, autofill?: string) {
|
||||||
|
const notification = std.getOptional(NotificationProvider);
|
||||||
|
if (!notification) return Promise.resolve(undefined);
|
||||||
|
|
||||||
|
return notification.prompt({
|
||||||
|
title: 'Create linked doc',
|
||||||
|
message: 'Enter a title for the new doc.',
|
||||||
|
placeholder: 'Untitled',
|
||||||
|
autofill,
|
||||||
|
confirmText: 'Confirm',
|
||||||
|
cancelText: 'Cancel',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function notifyDocCreated(std: BlockStdScope, doc: Doc) {
|
||||||
|
const notification = std.getOptional(NotificationProvider);
|
||||||
|
if (!notification) return;
|
||||||
|
|
||||||
|
const abortController = new AbortController();
|
||||||
|
const clear = () => {
|
||||||
|
doc.history.off('stack-item-added', addHandler);
|
||||||
|
doc.history.off('stack-item-popped', popHandler);
|
||||||
|
disposable.dispose();
|
||||||
|
};
|
||||||
|
const closeNotify = () => {
|
||||||
|
abortController.abort();
|
||||||
|
clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
// edit or undo or switch doc, close notify toast
|
||||||
|
const addHandler = doc.history.on('stack-item-added', closeNotify);
|
||||||
|
const popHandler = doc.history.on('stack-item-popped', closeNotify);
|
||||||
|
const disposable = std.host.slots.unmounted.on(closeNotify);
|
||||||
|
|
||||||
|
notification.notify({
|
||||||
|
title: 'Linked doc created',
|
||||||
|
message: 'You can click undo to recovery block content',
|
||||||
|
accent: 'info',
|
||||||
|
duration: 10 * 1000,
|
||||||
|
action: {
|
||||||
|
label: 'Undo',
|
||||||
|
onClick: () => {
|
||||||
|
doc.undo();
|
||||||
|
clear();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
abort: abortController.signal,
|
||||||
|
onClose: clear,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function convertSelectedBlocksToLinkedDoc(
|
||||||
|
std: BlockStdScope,
|
||||||
|
doc: Doc,
|
||||||
|
selectedModels: DraftModel[] | Promise<DraftModel[]>,
|
||||||
|
docTitle?: string
|
||||||
|
) {
|
||||||
|
const models = await selectedModels;
|
||||||
|
const slice = std.clipboard.sliceToSnapshot(Slice.fromModels(doc, models));
|
||||||
|
if (!slice) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const firstBlock = models[0];
|
||||||
|
if (!firstBlock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if title undefined, use the first heading block content as doc title
|
||||||
|
const title = docTitle || getTitleFromSelectedModels(models);
|
||||||
|
const linkedDoc = createLinkedDocFromSlice(std, doc, slice.content, title);
|
||||||
|
// insert linked doc card
|
||||||
|
doc.addSiblingBlocks(
|
||||||
|
doc.getBlock(firstBlock.id)!.model,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
flavour: 'affine:embed-linked-doc',
|
||||||
|
pageId: linkedDoc.id,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'before'
|
||||||
|
);
|
||||||
|
// delete selected elements
|
||||||
|
models.forEach(model => doc.deleteBlock(model));
|
||||||
|
return linkedDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createLinkedDocFromSlice(
|
||||||
|
std: BlockStdScope,
|
||||||
|
doc: Doc,
|
||||||
|
snapshots: BlockSnapshot[],
|
||||||
|
docTitle?: string
|
||||||
|
) {
|
||||||
|
// const modelsWithChildren = (list:BlockModel[]):BlockModel[]=>list.flatMap(model=>[model,...modelsWithChildren(model.children)])
|
||||||
|
const linkedDoc = doc.collection.createDoc({});
|
||||||
|
linkedDoc.load(() => {
|
||||||
|
const rootId = linkedDoc.addBlock('affine:page', {
|
||||||
|
title: new doc.Text(docTitle),
|
||||||
|
});
|
||||||
|
linkedDoc.addBlock('affine:surface', {}, rootId);
|
||||||
|
const noteId = linkedDoc.addBlock('affine:note', {}, rootId);
|
||||||
|
snapshots.forEach(snapshot => {
|
||||||
|
std.clipboard
|
||||||
|
.pasteBlockSnapshot(snapshot, linkedDoc, noteId)
|
||||||
|
.catch(console.error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return linkedDoc;
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export {
|
|||||||
LinkPreviewer,
|
LinkPreviewer,
|
||||||
type LinkPreviewResponseData,
|
type LinkPreviewResponseData,
|
||||||
} from './common/link-previewer.js';
|
} from './common/link-previewer.js';
|
||||||
export { getDocContentWithMaxLength } from './common/render-linked-doc';
|
export * from './common/render-linked-doc';
|
||||||
export { toEdgelessEmbedBlock } from './common/to-edgeless-embed-block';
|
export { toEdgelessEmbedBlock } from './common/to-edgeless-embed-block';
|
||||||
export * from './common/utils';
|
export * from './common/utils';
|
||||||
export * from './embed-figma-block';
|
export * from './embed-figma-block';
|
||||||
|
|||||||
43
blocksuite/affine/block-note/package.json
Normal file
43
blocksuite/affine/block-note/package.json
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "@blocksuite/affine-block-note",
|
||||||
|
"description": "Note 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",
|
||||||
|
"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__"
|
||||||
|
]
|
||||||
|
}
|
||||||
52
blocksuite/affine/block-note/src/effects.ts
Normal file
52
blocksuite/affine/block-note/src/effects.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import type { BlockComponent } from '@blocksuite/block-std';
|
||||||
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
|
import type { updateBlockType } from './commands/block-type';
|
||||||
|
import type { dedentBlock } from './commands/dedent-block';
|
||||||
|
import type { dedentBlockToRoot } from './commands/dedent-block-to-root';
|
||||||
|
import type { dedentBlocks } from './commands/dedent-blocks';
|
||||||
|
import type { dedentBlocksToRoot } from './commands/dedent-blocks-to-root';
|
||||||
|
import type { focusBlockEnd } from './commands/focus-block-end';
|
||||||
|
import type { focusBlockStart } from './commands/focus-block-start';
|
||||||
|
import type { indentBlock } from './commands/indent-block';
|
||||||
|
import type { indentBlocks } from './commands/indent-blocks';
|
||||||
|
import type { selectBlock } from './commands/select-block';
|
||||||
|
import type { selectBlocksBetween } from './commands/select-blocks-between';
|
||||||
|
import { NoteBlockComponent } from './note-block';
|
||||||
|
import {
|
||||||
|
EdgelessNoteBlockComponent,
|
||||||
|
EdgelessNoteMask,
|
||||||
|
} from './note-edgeless-block';
|
||||||
|
import type { NoteBlockService } from './note-service';
|
||||||
|
|
||||||
|
export function effects() {
|
||||||
|
customElements.define('affine-note', NoteBlockComponent);
|
||||||
|
customElements.define('edgeless-note-mask', EdgelessNoteMask);
|
||||||
|
customElements.define('affine-edgeless-note', EdgelessNoteBlockComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace BlockSuite {
|
||||||
|
interface Commands {
|
||||||
|
selectBlock: typeof selectBlock;
|
||||||
|
selectBlocksBetween: typeof selectBlocksBetween;
|
||||||
|
focusBlockStart: typeof focusBlockStart;
|
||||||
|
focusBlockEnd: typeof focusBlockEnd;
|
||||||
|
indentBlocks: typeof indentBlocks;
|
||||||
|
dedentBlock: typeof dedentBlock;
|
||||||
|
dedentBlocksToRoot: typeof dedentBlocksToRoot;
|
||||||
|
dedentBlocks: typeof dedentBlocks;
|
||||||
|
indentBlock: typeof indentBlock;
|
||||||
|
updateBlockType: typeof updateBlockType;
|
||||||
|
dedentBlockToRoot: typeof dedentBlockToRoot;
|
||||||
|
}
|
||||||
|
interface CommandContext {
|
||||||
|
focusBlock?: BlockComponent | null;
|
||||||
|
anchorBlock?: BlockComponent | null;
|
||||||
|
updatedBlocks?: BlockModel[];
|
||||||
|
}
|
||||||
|
interface BlockServices {
|
||||||
|
'affine:note': NoteBlockService;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
blocksuite/affine/block-note/src/index.ts
Normal file
6
blocksuite/affine/block-note/src/index.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export * from './adapters';
|
||||||
|
export * from './commands';
|
||||||
|
export * from './note-block';
|
||||||
|
export * from './note-edgeless-block';
|
||||||
|
export * from './note-service';
|
||||||
|
export * from './note-spec';
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
||||||
import { MoreIndicatorIcon } from '@blocksuite/affine-components/icons';
|
import { MoreIndicatorIcon } from '@blocksuite/affine-components/icons';
|
||||||
import type { NoteBlockModel } from '@blocksuite/affine-model';
|
import type { NoteBlockModel } from '@blocksuite/affine-model';
|
||||||
import {
|
import {
|
||||||
@@ -14,7 +13,11 @@ import {
|
|||||||
matchFlavours,
|
matchFlavours,
|
||||||
stopPropagation,
|
stopPropagation,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type { BlockComponent, EditorHost } from '@blocksuite/block-std';
|
import type {
|
||||||
|
BlockComponent,
|
||||||
|
BlockService,
|
||||||
|
EditorHost,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
import { ShadowlessElement, toGfxBlockComponent } from '@blocksuite/block-std';
|
import { ShadowlessElement, toGfxBlockComponent } from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
almostEqual,
|
almostEqual,
|
||||||
@@ -23,13 +26,12 @@ import {
|
|||||||
Point,
|
Point,
|
||||||
WithDisposable,
|
WithDisposable,
|
||||||
} from '@blocksuite/global/utils';
|
} from '@blocksuite/global/utils';
|
||||||
import type { BlockModel } from '@blocksuite/store';
|
import type { BlockModel, Slot } from '@blocksuite/store';
|
||||||
import { css, html, nothing } from 'lit';
|
import { css, html, nothing } from 'lit';
|
||||||
import { property, query, state } from 'lit/decorators.js';
|
import { property, query, state } from 'lit/decorators.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
import { styleMap } from 'lit/directives/style-map.js';
|
import { styleMap } from 'lit/directives/style-map.js';
|
||||||
|
|
||||||
import type { EdgelessRootService } from '../root-block/index.js';
|
|
||||||
import { NoteBlockComponent } from './note-block.js';
|
import { NoteBlockComponent } from './note-block.js';
|
||||||
|
|
||||||
export class EdgelessNoteMask extends WithDisposable(ShadowlessElement) {
|
export class EdgelessNoteMask extends WithDisposable(ShadowlessElement) {
|
||||||
@@ -151,7 +153,9 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
get rootService() {
|
get rootService() {
|
||||||
return this.std.getService('affine:page') as EdgelessRootService;
|
return this.std.getService('affine:page') as BlockService & {
|
||||||
|
slots: Record<string, Slot>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private _collapsedContent() {
|
private _collapsedContent() {
|
||||||
@@ -312,7 +316,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
|
|||||||
override connectedCallback(): void {
|
override connectedCallback(): void {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
|
|
||||||
const selection = this.rootService.selection;
|
const selection = this.gfx.selection;
|
||||||
|
|
||||||
this._editing = selection.has(this.model.id) && selection.editing;
|
this._editing = selection.has(this.model.id) && selection.editing;
|
||||||
this._disposables.add(
|
this._disposables.add(
|
||||||
@@ -328,7 +332,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
|
|||||||
|
|
||||||
override firstUpdated() {
|
override firstUpdated() {
|
||||||
const { _disposables } = this;
|
const { _disposables } = this;
|
||||||
const selection = this.rootService.selection;
|
const selection = this.gfx.selection;
|
||||||
|
|
||||||
_disposables.add(
|
_disposables.add(
|
||||||
this.rootService.slots.elementResizeStart.on(() => {
|
this.rootService.slots.elementResizeStart.on(() => {
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { textConversionConfigs } from '@blocksuite/affine-components/rich-text';
|
||||||
import { NoteBlockSchema } from '@blocksuite/affine-model';
|
import { NoteBlockSchema } from '@blocksuite/affine-model';
|
||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||||
import {
|
import {
|
||||||
@@ -5,14 +6,14 @@ import {
|
|||||||
type BlockComponent,
|
type BlockComponent,
|
||||||
type BlockSelection,
|
type BlockSelection,
|
||||||
BlockService,
|
BlockService,
|
||||||
|
type BlockStdScope,
|
||||||
type UIEventHandler,
|
type UIEventHandler,
|
||||||
type UIEventStateContext,
|
type UIEventStateContext,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
import { moveBlockConfigs } from '../_common/configs/move-block.js';
|
import { moveBlockConfigs } from './move-block';
|
||||||
import { quickActionConfig } from '../_common/configs/quick-action/config.js';
|
import { quickActionConfig } from './quick-action';
|
||||||
import { textConversionConfigs } from '../_common/configs/text-conversion.js';
|
|
||||||
import { onModelElementUpdated } from '../root-block/utils/callback.js';
|
|
||||||
|
|
||||||
export class NoteBlockService extends BlockService {
|
export class NoteBlockService extends BlockService {
|
||||||
static override readonly flavour = NoteBlockSchema.model.flavour;
|
static override readonly flavour = NoteBlockSchema.model.flavour;
|
||||||
@@ -51,10 +52,10 @@ export class NoteBlockService extends BlockService {
|
|||||||
return {
|
return {
|
||||||
...acc,
|
...acc,
|
||||||
[config.hotkey!]: ctx => {
|
[config.hotkey!]: ctx => {
|
||||||
if (!config.showWhen(this.std.host)) return;
|
if (!config.showWhen(this.std)) return;
|
||||||
|
|
||||||
ctx.get('defaultState').event.preventDefault();
|
ctx.get('defaultState').event.preventDefault();
|
||||||
config.action(this.std.host);
|
config.action(this.std);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -83,8 +84,7 @@ export class NoteBlockService extends BlockService {
|
|||||||
})
|
})
|
||||||
.inline((ctx, next) => {
|
.inline((ctx, next) => {
|
||||||
const newModels = ctx.updatedBlocks;
|
const newModels = ctx.updatedBlocks;
|
||||||
const host = ctx.std.host;
|
if (!newModels) {
|
||||||
if (!host || !newModels) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ export class NoteBlockService extends BlockService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [codeModel] = newModels;
|
const [codeModel] = newModels;
|
||||||
onModelElementUpdated(host, codeModel, codeElement => {
|
onModelElementUpdated(ctx.std, codeModel, codeElement => {
|
||||||
this._std.selection.setGroup('note', [
|
this._std.selection.setGroup('note', [
|
||||||
this._std.selection.create('text', {
|
this._std.selection.create('text', {
|
||||||
from: {
|
from: {
|
||||||
@@ -584,3 +584,19 @@ export class NoteBlockService extends BlockService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onModelElementUpdated(
|
||||||
|
std: BlockStdScope,
|
||||||
|
model: BlockModel,
|
||||||
|
callback: (block: BlockComponent) => void
|
||||||
|
) {
|
||||||
|
const page = model.doc;
|
||||||
|
if (!page.root) return;
|
||||||
|
|
||||||
|
const rootComponent = std.view.getBlock(page.root.id);
|
||||||
|
if (!rootComponent) return;
|
||||||
|
await rootComponent.updateComplete;
|
||||||
|
|
||||||
|
const element = std.view.getBlock(model.id);
|
||||||
|
if (element) callback(element);
|
||||||
|
}
|
||||||
62
blocksuite/affine/block-note/src/quick-action.ts
Normal file
62
blocksuite/affine/block-note/src/quick-action.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import {
|
||||||
|
convertSelectedBlocksToLinkedDoc,
|
||||||
|
getTitleFromSelectedModels,
|
||||||
|
notifyDocCreated,
|
||||||
|
promptDocTitle,
|
||||||
|
} from '@blocksuite/affine-block-embed';
|
||||||
|
import type { BlockStdScope } from '@blocksuite/block-std';
|
||||||
|
|
||||||
|
export interface QuickActionConfig {
|
||||||
|
id: string;
|
||||||
|
hotkey?: string;
|
||||||
|
showWhen: (std: BlockStdScope) => boolean;
|
||||||
|
action: (std: BlockStdScope) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const quickActionConfig: QuickActionConfig[] = [
|
||||||
|
{
|
||||||
|
id: 'convert-to-linked-doc',
|
||||||
|
hotkey: `Mod-Shift-l`,
|
||||||
|
showWhen: std => {
|
||||||
|
const [_, ctx] = std.command
|
||||||
|
.chain()
|
||||||
|
.getSelectedModels({
|
||||||
|
types: ['block'],
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
const { selectedModels } = ctx;
|
||||||
|
return !!selectedModels && selectedModels.length > 0;
|
||||||
|
},
|
||||||
|
action: std => {
|
||||||
|
const [_, ctx] = std.command
|
||||||
|
.chain()
|
||||||
|
.getSelectedModels({
|
||||||
|
types: ['block'],
|
||||||
|
mode: 'highest',
|
||||||
|
})
|
||||||
|
.draftSelectedModels()
|
||||||
|
.run();
|
||||||
|
const { selectedModels, draftedModels } = ctx;
|
||||||
|
if (!selectedModels) return;
|
||||||
|
|
||||||
|
if (!selectedModels.length || !draftedModels) return;
|
||||||
|
|
||||||
|
std.selection.clear();
|
||||||
|
|
||||||
|
const doc = std.doc;
|
||||||
|
const autofill = getTitleFromSelectedModels(selectedModels);
|
||||||
|
promptDocTitle(std, autofill)
|
||||||
|
.then(title => {
|
||||||
|
if (title === null) return;
|
||||||
|
convertSelectedBlocksToLinkedDoc(
|
||||||
|
std,
|
||||||
|
doc,
|
||||||
|
draftedModels,
|
||||||
|
title
|
||||||
|
).catch(console.error);
|
||||||
|
notifyDocCreated(std, doc);
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
35
blocksuite/affine/block-note/tsconfig.json
Normal file
35
blocksuite/affine/block-note/tsconfig.json
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import type { TemplateResult } from 'lit';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BulletedListIcon,
|
BulletedListIcon,
|
||||||
CheckBoxIcon,
|
CheckBoxIcon,
|
||||||
@@ -12,8 +14,7 @@ import {
|
|||||||
NumberedListIcon,
|
NumberedListIcon,
|
||||||
QuoteIcon,
|
QuoteIcon,
|
||||||
TextIcon,
|
TextIcon,
|
||||||
} from '@blocksuite/affine-components/icons';
|
} from '../icons';
|
||||||
import type { TemplateResult } from 'lit';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text primitive entries used in slash menu and format bar,
|
* Text primitive entries used in slash menu and format bar,
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from './all-extensions.js';
|
export * from './all-extensions';
|
||||||
|
export { type TextConversionConfig, textConversionConfigs } from './conversion';
|
||||||
export {
|
export {
|
||||||
asyncGetRichText,
|
asyncGetRichText,
|
||||||
asyncSetInlineRange,
|
asyncSetInlineRange,
|
||||||
@@ -7,9 +8,9 @@ export {
|
|||||||
getRichTextByModel,
|
getRichTextByModel,
|
||||||
onModelTextUpdated,
|
onModelTextUpdated,
|
||||||
selectTextModel,
|
selectTextModel,
|
||||||
} from './dom.js';
|
} from './dom';
|
||||||
export * from './effects.js';
|
export * from './effects';
|
||||||
export * from './extension/index.js';
|
export * from './extension';
|
||||||
export {
|
export {
|
||||||
clearMarksOnDiscontinuousInput,
|
clearMarksOnDiscontinuousInput,
|
||||||
FORMAT_BLOCK_SUPPORT_FLAVOURS,
|
FORMAT_BLOCK_SUPPORT_FLAVOURS,
|
||||||
@@ -20,9 +21,9 @@ export {
|
|||||||
textCommands,
|
textCommands,
|
||||||
type TextFormatConfig,
|
type TextFormatConfig,
|
||||||
textFormatConfigs,
|
textFormatConfigs,
|
||||||
} from './format/index.js';
|
} from './format';
|
||||||
export * from './inline/index.js';
|
export * from './inline';
|
||||||
export { textKeymap } from './keymap/index.js';
|
export { textKeymap } from './keymap';
|
||||||
export { insertLinkedNode } from './linked-node.js';
|
export { insertLinkedNode } from './linked-node';
|
||||||
export { markdownInput } from './markdown/index.js';
|
export { markdownInput } from './markdown';
|
||||||
export { RichText } from './rich-text.js';
|
export { RichText } from './rich-text';
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"@blocksuite/affine-block-embed": "workspace:*",
|
"@blocksuite/affine-block-embed": "workspace:*",
|
||||||
"@blocksuite/affine-block-image": "workspace:*",
|
"@blocksuite/affine-block-image": "workspace:*",
|
||||||
"@blocksuite/affine-block-list": "workspace:*",
|
"@blocksuite/affine-block-list": "workspace:*",
|
||||||
|
"@blocksuite/affine-block-note": "workspace:*",
|
||||||
"@blocksuite/affine-block-paragraph": "workspace:*",
|
"@blocksuite/affine-block-paragraph": "workspace:*",
|
||||||
"@blocksuite/affine-block-surface": "workspace:*",
|
"@blocksuite/affine-block-surface": "workspace:*",
|
||||||
"@blocksuite/affine-components": "workspace:*",
|
"@blocksuite/affine-components": "workspace:*",
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
import {
|
|
||||||
CopyIcon,
|
|
||||||
DatabaseTableViewIcon20,
|
|
||||||
LinkedDocIcon,
|
|
||||||
} from '@blocksuite/affine-components/icons';
|
|
||||||
import { toast } from '@blocksuite/affine-components/toast';
|
|
||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
|
||||||
import type { EditorHost } from '@blocksuite/block-std';
|
|
||||||
import { tableViewMeta } from '@blocksuite/data-view/view-presets';
|
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
|
||||||
import type { TemplateResult } from 'lit';
|
|
||||||
|
|
||||||
import { convertToDatabase } from '../../../database-block/data-source.js';
|
|
||||||
import { DATABASE_CONVERT_WHITE_LIST } from '../../../database-block/utils/block-utils.js';
|
|
||||||
import {
|
|
||||||
convertSelectedBlocksToLinkedDoc,
|
|
||||||
getTitleFromSelectedModels,
|
|
||||||
notifyDocCreated,
|
|
||||||
promptDocTitle,
|
|
||||||
} from '../../utils/render-linked-doc.js';
|
|
||||||
|
|
||||||
export interface QuickActionConfig {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
disabledToolTip?: string;
|
|
||||||
icon: TemplateResult<1>;
|
|
||||||
hotkey?: string;
|
|
||||||
showWhen: (host: EditorHost) => boolean;
|
|
||||||
enabledWhen: (host: EditorHost) => boolean;
|
|
||||||
action: (host: EditorHost) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const quickActionConfig: QuickActionConfig[] = [
|
|
||||||
{
|
|
||||||
id: 'copy',
|
|
||||||
name: 'Copy',
|
|
||||||
disabledToolTip: undefined,
|
|
||||||
icon: CopyIcon,
|
|
||||||
hotkey: undefined,
|
|
||||||
showWhen: () => true,
|
|
||||||
enabledWhen: () => true,
|
|
||||||
action: host => {
|
|
||||||
host.std.command
|
|
||||||
.chain()
|
|
||||||
.getSelectedModels()
|
|
||||||
.with({
|
|
||||||
onCopy: () => {
|
|
||||||
toast(host, 'Copied to clipboard');
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.draftSelectedModels()
|
|
||||||
.copySelectedModels()
|
|
||||||
.run();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'convert-to-database',
|
|
||||||
name: 'Group as Table',
|
|
||||||
disabledToolTip:
|
|
||||||
'Contains Block types that cannot be converted to Database',
|
|
||||||
icon: DatabaseTableViewIcon20,
|
|
||||||
showWhen: host => {
|
|
||||||
const [_, ctx] = host.std.command
|
|
||||||
.chain()
|
|
||||||
.getSelectedModels({
|
|
||||||
types: ['block', 'text'],
|
|
||||||
})
|
|
||||||
.run();
|
|
||||||
const { selectedModels } = ctx;
|
|
||||||
if (!selectedModels || selectedModels.length === 0) return false;
|
|
||||||
|
|
||||||
const firstBlock = selectedModels[0];
|
|
||||||
assertExists(firstBlock);
|
|
||||||
if (matchFlavours(firstBlock, ['affine:database'])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
enabledWhen: host => {
|
|
||||||
const [_, ctx] = host.std.command
|
|
||||||
.chain()
|
|
||||||
.getSelectedModels({
|
|
||||||
types: ['block', 'text'],
|
|
||||||
})
|
|
||||||
.run();
|
|
||||||
const { selectedModels } = ctx;
|
|
||||||
if (!selectedModels || selectedModels.length === 0) return false;
|
|
||||||
|
|
||||||
return selectedModels.every(block =>
|
|
||||||
DATABASE_CONVERT_WHITE_LIST.includes(block.flavour)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
action: host => {
|
|
||||||
convertToDatabase(host, tableViewMeta.type);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'convert-to-linked-doc',
|
|
||||||
name: 'Create Linked Doc',
|
|
||||||
icon: LinkedDocIcon,
|
|
||||||
hotkey: `Mod-Shift-l`,
|
|
||||||
showWhen: host => {
|
|
||||||
const [_, ctx] = host.std.command
|
|
||||||
.chain()
|
|
||||||
.getSelectedModels({
|
|
||||||
types: ['block'],
|
|
||||||
})
|
|
||||||
.run();
|
|
||||||
const { selectedModels } = ctx;
|
|
||||||
return !!selectedModels && selectedModels.length > 0;
|
|
||||||
},
|
|
||||||
enabledWhen: host => {
|
|
||||||
const [_, ctx] = host.std.command
|
|
||||||
.chain()
|
|
||||||
.getSelectedModels({
|
|
||||||
types: ['block'],
|
|
||||||
})
|
|
||||||
.run();
|
|
||||||
const { selectedModels } = ctx;
|
|
||||||
return !!selectedModels && selectedModels.length > 0;
|
|
||||||
},
|
|
||||||
action: host => {
|
|
||||||
const [_, ctx] = host.std.command
|
|
||||||
.chain()
|
|
||||||
.getSelectedModels({
|
|
||||||
types: ['block'],
|
|
||||||
mode: 'highest',
|
|
||||||
})
|
|
||||||
.draftSelectedModels()
|
|
||||||
.run();
|
|
||||||
const { selectedModels, draftedModels } = ctx;
|
|
||||||
assertExists(selectedModels);
|
|
||||||
if (!selectedModels.length || !draftedModels) return;
|
|
||||||
|
|
||||||
host.selection.clear();
|
|
||||||
|
|
||||||
const doc = host.doc;
|
|
||||||
const autofill = getTitleFromSelectedModels(selectedModels);
|
|
||||||
promptDocTitle(host, autofill)
|
|
||||||
.then(title => {
|
|
||||||
if (title === null) return;
|
|
||||||
convertSelectedBlocksToLinkedDoc(
|
|
||||||
host.std,
|
|
||||||
doc,
|
|
||||||
draftedModels,
|
|
||||||
title
|
|
||||||
).catch(console.error);
|
|
||||||
notifyDocCreated(host, doc);
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
@@ -1,19 +1,9 @@
|
|||||||
import type { FrameBlockModel, NoteBlockModel } from '@blocksuite/affine-model';
|
import type { FrameBlockModel, NoteBlockModel } from '@blocksuite/affine-model';
|
||||||
import { NoteDisplayMode } from '@blocksuite/affine-model';
|
import { NoteDisplayMode } from '@blocksuite/affine-model';
|
||||||
import {
|
import { DocModeProvider } from '@blocksuite/affine-shared/services';
|
||||||
DocModeProvider,
|
import { getBlockProps } from '@blocksuite/affine-shared/utils';
|
||||||
NotificationProvider,
|
|
||||||
} from '@blocksuite/affine-shared/services';
|
|
||||||
import { getBlockProps, matchFlavours } from '@blocksuite/affine-shared/utils';
|
|
||||||
import type { EditorHost } from '@blocksuite/block-std';
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { type BlockModel, type Doc } from '@blocksuite/store';
|
||||||
import {
|
|
||||||
type BlockModel,
|
|
||||||
type BlockSnapshot,
|
|
||||||
type Doc,
|
|
||||||
type DraftModel,
|
|
||||||
Slice,
|
|
||||||
} from '@blocksuite/store';
|
|
||||||
|
|
||||||
import { GfxBlockModel } from '../../root-block/edgeless/block-model.js';
|
import { GfxBlockModel } from '../../root-block/edgeless/block-model.js';
|
||||||
import {
|
import {
|
||||||
@@ -27,68 +17,6 @@ import {
|
|||||||
} from '../../root-block/edgeless/utils/query.js';
|
} from '../../root-block/edgeless/utils/query.js';
|
||||||
import { getSurfaceBlock } from '../../surface-ref-block/utils.js';
|
import { getSurfaceBlock } from '../../surface-ref-block/utils.js';
|
||||||
|
|
||||||
export function promptDocTitle(host: EditorHost, autofill?: string) {
|
|
||||||
const notification = host.std.getOptional(NotificationProvider);
|
|
||||||
if (!notification) return Promise.resolve(undefined);
|
|
||||||
|
|
||||||
return notification.prompt({
|
|
||||||
title: 'Create linked doc',
|
|
||||||
message: 'Enter a title for the new doc.',
|
|
||||||
placeholder: 'Untitled',
|
|
||||||
autofill,
|
|
||||||
confirmText: 'Confirm',
|
|
||||||
cancelText: 'Cancel',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getTitleFromSelectedModels(selectedModels: DraftModel[]) {
|
|
||||||
const firstBlock = selectedModels[0];
|
|
||||||
if (
|
|
||||||
matchFlavours(firstBlock, ['affine:paragraph']) &&
|
|
||||||
firstBlock.type.startsWith('h')
|
|
||||||
) {
|
|
||||||
return firstBlock.text.toString();
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function notifyDocCreated(host: EditorHost, doc: Doc) {
|
|
||||||
const notification = host.std.getOptional(NotificationProvider);
|
|
||||||
if (!notification) return;
|
|
||||||
|
|
||||||
const abortController = new AbortController();
|
|
||||||
const clear = () => {
|
|
||||||
doc.history.off('stack-item-added', addHandler);
|
|
||||||
doc.history.off('stack-item-popped', popHandler);
|
|
||||||
disposable.dispose();
|
|
||||||
};
|
|
||||||
const closeNotify = () => {
|
|
||||||
abortController.abort();
|
|
||||||
clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
// edit or undo or switch doc, close notify toast
|
|
||||||
const addHandler = doc.history.on('stack-item-added', closeNotify);
|
|
||||||
const popHandler = doc.history.on('stack-item-popped', closeNotify);
|
|
||||||
const disposable = host.slots.unmounted.on(closeNotify);
|
|
||||||
|
|
||||||
notification.notify({
|
|
||||||
title: 'Linked doc created',
|
|
||||||
message: 'You can click undo to recovery block content',
|
|
||||||
accent: 'info',
|
|
||||||
duration: 10 * 1000,
|
|
||||||
action: {
|
|
||||||
label: 'Undo',
|
|
||||||
onClick: () => {
|
|
||||||
doc.undo();
|
|
||||||
clear();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
abort: abortController.signal,
|
|
||||||
onClose: clear,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addBlocksToDoc(
|
export function addBlocksToDoc(
|
||||||
targetDoc: Doc,
|
targetDoc: Doc,
|
||||||
model: BlockModel,
|
model: BlockModel,
|
||||||
@@ -110,61 +38,6 @@ export function addBlocksToDoc(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function convertSelectedBlocksToLinkedDoc(
|
|
||||||
std: BlockSuite.Std,
|
|
||||||
doc: Doc,
|
|
||||||
selectedModels: DraftModel[] | Promise<DraftModel[]>,
|
|
||||||
docTitle?: string
|
|
||||||
) {
|
|
||||||
const models = await selectedModels;
|
|
||||||
const slice = std.clipboard.sliceToSnapshot(Slice.fromModels(doc, models));
|
|
||||||
if (!slice) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const firstBlock = models[0];
|
|
||||||
assertExists(firstBlock);
|
|
||||||
// if title undefined, use the first heading block content as doc title
|
|
||||||
const title = docTitle || getTitleFromSelectedModels(models);
|
|
||||||
const linkedDoc = createLinkedDocFromSlice(std, doc, slice.content, title);
|
|
||||||
// insert linked doc card
|
|
||||||
doc.addSiblingBlocks(
|
|
||||||
doc.getBlock(firstBlock.id)!.model,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
flavour: 'affine:embed-linked-doc',
|
|
||||||
pageId: linkedDoc.id,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'before'
|
|
||||||
);
|
|
||||||
// delete selected elements
|
|
||||||
models.forEach(model => doc.deleteBlock(model));
|
|
||||||
return linkedDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createLinkedDocFromSlice(
|
|
||||||
std: BlockSuite.Std,
|
|
||||||
doc: Doc,
|
|
||||||
snapshots: BlockSnapshot[],
|
|
||||||
docTitle?: string
|
|
||||||
) {
|
|
||||||
// const modelsWithChildren = (list:BlockModel[]):BlockModel[]=>list.flatMap(model=>[model,...modelsWithChildren(model.children)])
|
|
||||||
const linkedDoc = doc.collection.createDoc({});
|
|
||||||
linkedDoc.load(() => {
|
|
||||||
const rootId = linkedDoc.addBlock('affine:page', {
|
|
||||||
title: new doc.Text(docTitle),
|
|
||||||
});
|
|
||||||
linkedDoc.addBlock('affine:surface', {}, rootId);
|
|
||||||
const noteId = linkedDoc.addBlock('affine:note', {}, rootId);
|
|
||||||
snapshots.forEach(snapshot => {
|
|
||||||
std.clipboard
|
|
||||||
.pasteBlockSnapshot(snapshot, linkedDoc, noteId)
|
|
||||||
.catch(console.error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return linkedDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createLinkedDocFromNote(
|
export function createLinkedDocFromNote(
|
||||||
doc: Doc,
|
doc: Doc,
|
||||||
note: NoteBlockModel,
|
note: NoteBlockModel,
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
|
|||||||
import { EmbedExtensions } from '@blocksuite/affine-block-embed';
|
import { EmbedExtensions } from '@blocksuite/affine-block-embed';
|
||||||
import { ImageBlockSpec } from '@blocksuite/affine-block-image';
|
import { ImageBlockSpec } from '@blocksuite/affine-block-image';
|
||||||
import { ListBlockSpec } from '@blocksuite/affine-block-list';
|
import { ListBlockSpec } from '@blocksuite/affine-block-list';
|
||||||
|
import {
|
||||||
|
EdgelessNoteBlockSpec,
|
||||||
|
NoteBlockSpec,
|
||||||
|
} from '@blocksuite/affine-block-note';
|
||||||
import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph';
|
import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph';
|
||||||
import { RichTextExtensions } from '@blocksuite/affine-components/rich-text';
|
import { RichTextExtensions } from '@blocksuite/affine-components/rich-text';
|
||||||
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
||||||
@@ -13,10 +17,6 @@ import { CodeBlockSpec } from '../code-block/code-block-spec.js';
|
|||||||
import { DataViewBlockSpec } from '../data-view-block/data-view-spec.js';
|
import { DataViewBlockSpec } from '../data-view-block/data-view-spec.js';
|
||||||
import { DatabaseBlockSpec } from '../database-block/database-spec.js';
|
import { DatabaseBlockSpec } from '../database-block/database-spec.js';
|
||||||
import { DividerBlockSpec } from '../divider-block/divider-spec.js';
|
import { DividerBlockSpec } from '../divider-block/divider-spec.js';
|
||||||
import {
|
|
||||||
EdgelessNoteBlockSpec,
|
|
||||||
NoteBlockSpec,
|
|
||||||
} from '../note-block/note-spec.js';
|
|
||||||
|
|
||||||
export const CommonFirstPartyBlockSpecs: ExtensionType[] = [
|
export const CommonFirstPartyBlockSpecs: ExtensionType[] = [
|
||||||
RichTextExtensions,
|
RichTextExtensions,
|
||||||
|
|||||||
@@ -11,16 +11,16 @@ import {
|
|||||||
} from '@blocksuite/affine-block-embed';
|
} from '@blocksuite/affine-block-embed';
|
||||||
import { ImageBlockSpec } from '@blocksuite/affine-block-image';
|
import { ImageBlockSpec } from '@blocksuite/affine-block-image';
|
||||||
import { ListBlockSpec } from '@blocksuite/affine-block-list';
|
import { ListBlockSpec } from '@blocksuite/affine-block-list';
|
||||||
|
import {
|
||||||
|
EdgelessNoteBlockSpec,
|
||||||
|
NoteBlockSpec,
|
||||||
|
} from '@blocksuite/affine-block-note';
|
||||||
import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph';
|
import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph';
|
||||||
|
|
||||||
import { CodeBlockSpec } from '../../code-block/code-block-spec.js';
|
import { CodeBlockSpec } from '../../code-block/code-block-spec.js';
|
||||||
import { DataViewBlockSpec } from '../../data-view-block/data-view-spec.js';
|
import { DataViewBlockSpec } from '../../data-view-block/data-view-spec.js';
|
||||||
import { DatabaseBlockSpec } from '../../database-block/database-spec.js';
|
import { DatabaseBlockSpec } from '../../database-block/database-spec.js';
|
||||||
import { DividerBlockSpec } from '../../divider-block/divider-spec.js';
|
import { DividerBlockSpec } from '../../divider-block/divider-spec.js';
|
||||||
import {
|
|
||||||
EdgelessNoteBlockSpec,
|
|
||||||
NoteBlockSpec,
|
|
||||||
} from '../../note-block/note-spec.js';
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
AttachmentBlockSpec,
|
AttachmentBlockSpec,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { NoteBlockComponent } from '@blocksuite/affine-block-note';
|
||||||
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||||
import {
|
import {
|
||||||
menu,
|
menu,
|
||||||
@@ -40,7 +41,6 @@ import { html } from 'lit/static-html.js';
|
|||||||
|
|
||||||
import { BlockRenderer } from '../database-block/detail-panel/block-renderer.js';
|
import { BlockRenderer } from '../database-block/detail-panel/block-renderer.js';
|
||||||
import { NoteRenderer } from '../database-block/detail-panel/note-renderer.js';
|
import { NoteRenderer } from '../database-block/detail-panel/note-renderer.js';
|
||||||
import type { NoteBlockComponent } from '../note-block/index.js';
|
|
||||||
import {
|
import {
|
||||||
EdgelessRootBlockComponent,
|
EdgelessRootBlockComponent,
|
||||||
type RootService,
|
type RootService,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { NoteBlockComponent } from '@blocksuite/affine-block-note';
|
||||||
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||||
import {
|
import {
|
||||||
menu,
|
menu,
|
||||||
@@ -44,7 +45,6 @@ import { autoUpdate } from '@floating-ui/dom';
|
|||||||
import { computed, signal } from '@preact/signals-core';
|
import { computed, signal } from '@preact/signals-core';
|
||||||
import { css, html, nothing, unsafeCSS } from 'lit';
|
import { css, html, nothing, unsafeCSS } from 'lit';
|
||||||
|
|
||||||
import type { NoteBlockComponent } from '../note-block/index.js';
|
|
||||||
import { EdgelessRootBlockComponent } from '../root-block/index.js';
|
import { EdgelessRootBlockComponent } from '../root-block/index.js';
|
||||||
import { getDropResult } from '../root-block/widgets/drag-handle/utils.js';
|
import { getDropResult } from '../root-block/widgets/drag-handle/utils.js';
|
||||||
import { popSideDetail } from './components/layout.js';
|
import { popSideDetail } from './components/layout.js';
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { effects as blockBookmarkEffects } from '@blocksuite/affine-block-bookma
|
|||||||
import { effects as blockEmbedEffects } from '@blocksuite/affine-block-embed/effects';
|
import { effects as blockEmbedEffects } from '@blocksuite/affine-block-embed/effects';
|
||||||
import { effects as blockImageEffects } from '@blocksuite/affine-block-image/effects';
|
import { effects as blockImageEffects } from '@blocksuite/affine-block-image/effects';
|
||||||
import { effects as blockListEffects } from '@blocksuite/affine-block-list/effects';
|
import { effects as blockListEffects } from '@blocksuite/affine-block-list/effects';
|
||||||
|
import { effects as blockNoteEffects } from '@blocksuite/affine-block-note/effects';
|
||||||
import { effects as blockParagraphEffects } from '@blocksuite/affine-block-paragraph/effects';
|
import { effects as blockParagraphEffects } from '@blocksuite/affine-block-paragraph/effects';
|
||||||
import { effects as blockSurfaceEffects } from '@blocksuite/affine-block-surface/effects';
|
import { effects as blockSurfaceEffects } from '@blocksuite/affine-block-surface/effects';
|
||||||
import { effects as componentAiItemEffects } from '@blocksuite/affine-components/ai-item';
|
import { effects as componentAiItemEffects } from '@blocksuite/affine-components/ai-item';
|
||||||
@@ -66,23 +67,6 @@ import { EdgelessTextBlockComponent } from './edgeless-text-block/index.js';
|
|||||||
import { FrameBlockComponent } from './frame-block/index.js';
|
import { FrameBlockComponent } from './frame-block/index.js';
|
||||||
import { effects as blockLatexEffects } from './latex-block/effects.js';
|
import { effects as blockLatexEffects } from './latex-block/effects.js';
|
||||||
import { LatexBlockComponent } from './latex-block/index.js';
|
import { LatexBlockComponent } from './latex-block/index.js';
|
||||||
import type { updateBlockType } from './note-block/commands/block-type.js';
|
|
||||||
import type { dedentBlock } from './note-block/commands/dedent-block.js';
|
|
||||||
import type { dedentBlockToRoot } from './note-block/commands/dedent-block-to-root.js';
|
|
||||||
import type { dedentBlocks } from './note-block/commands/dedent-blocks.js';
|
|
||||||
import type { dedentBlocksToRoot } from './note-block/commands/dedent-blocks-to-root.js';
|
|
||||||
import type { focusBlockEnd } from './note-block/commands/focus-block-end.js';
|
|
||||||
import type { focusBlockStart } from './note-block/commands/focus-block-start.js';
|
|
||||||
import type { indentBlock } from './note-block/commands/indent-block.js';
|
|
||||||
import type { indentBlocks } from './note-block/commands/indent-blocks.js';
|
|
||||||
import type { selectBlock } from './note-block/commands/select-block.js';
|
|
||||||
import type { selectBlocksBetween } from './note-block/commands/select-blocks-between.js';
|
|
||||||
import {
|
|
||||||
EdgelessNoteBlockComponent,
|
|
||||||
EdgelessNoteMask,
|
|
||||||
NoteBlockComponent,
|
|
||||||
type NoteBlockService,
|
|
||||||
} from './note-block/index.js';
|
|
||||||
import { EdgelessAutoCompletePanel } from './root-block/edgeless/components/auto-complete/auto-complete-panel.js';
|
import { EdgelessAutoCompletePanel } from './root-block/edgeless/components/auto-complete/auto-complete-panel.js';
|
||||||
import { EdgelessAutoComplete } from './root-block/edgeless/components/auto-complete/edgeless-auto-complete.js';
|
import { EdgelessAutoComplete } from './root-block/edgeless/components/auto-complete/edgeless-auto-complete.js';
|
||||||
import { EdgelessToolIconButton } from './root-block/edgeless/components/buttons/tool-icon-button.js';
|
import { EdgelessToolIconButton } from './root-block/edgeless/components/buttons/tool-icon-button.js';
|
||||||
@@ -264,6 +248,7 @@ export function effects() {
|
|||||||
stdEffects();
|
stdEffects();
|
||||||
inlineEffects();
|
inlineEffects();
|
||||||
|
|
||||||
|
blockNoteEffects();
|
||||||
blockAttachmentEffects();
|
blockAttachmentEffects();
|
||||||
blockBookmarkEffects();
|
blockBookmarkEffects();
|
||||||
blockListEffects();
|
blockListEffects();
|
||||||
@@ -314,8 +299,6 @@ export function effects() {
|
|||||||
customElements.define('database-datasource-block-renderer', BlockRenderer);
|
customElements.define('database-datasource-block-renderer', BlockRenderer);
|
||||||
customElements.define('affine-latex', LatexBlockComponent);
|
customElements.define('affine-latex', LatexBlockComponent);
|
||||||
customElements.define('affine-page-root', PageRootBlockComponent);
|
customElements.define('affine-page-root', PageRootBlockComponent);
|
||||||
customElements.define('edgeless-note-mask', EdgelessNoteMask);
|
|
||||||
customElements.define('affine-edgeless-note', EdgelessNoteBlockComponent);
|
|
||||||
customElements.define('affine-preview-root', PreviewRootBlockComponent);
|
customElements.define('affine-preview-root', PreviewRootBlockComponent);
|
||||||
customElements.define('affine-code', CodeBlockComponent);
|
customElements.define('affine-code', CodeBlockComponent);
|
||||||
customElements.define('mini-mindmap-preview', MiniMindmapPreview);
|
customElements.define('mini-mindmap-preview', MiniMindmapPreview);
|
||||||
@@ -445,7 +428,6 @@ export function effects() {
|
|||||||
customElements.define('edgeless-present-button', EdgelessPresentButton);
|
customElements.define('edgeless-present-button', EdgelessPresentButton);
|
||||||
customElements.define('edgeless-color-picker', EdgelessColorPicker);
|
customElements.define('edgeless-color-picker', EdgelessColorPicker);
|
||||||
customElements.define('overlay-scrollbar', OverlayScrollbar);
|
customElements.define('overlay-scrollbar', OverlayScrollbar);
|
||||||
customElements.define('affine-note', NoteBlockComponent);
|
|
||||||
customElements.define('affine-template-loading', AffineTemplateLoading);
|
customElements.define('affine-template-loading', AffineTemplateLoading);
|
||||||
customElements.define(
|
customElements.define(
|
||||||
'edgeless-color-picker-button',
|
'edgeless-color-picker-button',
|
||||||
@@ -549,18 +531,7 @@ export function effects() {
|
|||||||
declare global {
|
declare global {
|
||||||
namespace BlockSuite {
|
namespace BlockSuite {
|
||||||
interface Commands {
|
interface Commands {
|
||||||
selectBlock: typeof selectBlock;
|
|
||||||
selectBlocksBetween: typeof selectBlocksBetween;
|
|
||||||
focusBlockStart: typeof focusBlockStart;
|
|
||||||
focusBlockEnd: typeof focusBlockEnd;
|
|
||||||
indentBlocks: typeof indentBlocks;
|
|
||||||
dedentBlock: typeof dedentBlock;
|
|
||||||
dedentBlocksToRoot: typeof dedentBlocksToRoot;
|
|
||||||
dedentBlocks: typeof dedentBlocks;
|
|
||||||
indentBlock: typeof indentBlock;
|
|
||||||
updateBlockType: typeof updateBlockType;
|
|
||||||
insertEdgelessText: typeof insertEdgelessTextCommand;
|
insertEdgelessText: typeof insertEdgelessTextCommand;
|
||||||
dedentBlockToRoot: typeof dedentBlockToRoot;
|
|
||||||
}
|
}
|
||||||
interface CommandContext {
|
interface CommandContext {
|
||||||
focusBlock?: BlockComponent | null;
|
focusBlock?: BlockComponent | null;
|
||||||
@@ -573,7 +544,6 @@ declare global {
|
|||||||
'affine:page': RootBlockConfig;
|
'affine:page': RootBlockConfig;
|
||||||
}
|
}
|
||||||
interface BlockServices {
|
interface BlockServices {
|
||||||
'affine:note': NoteBlockService;
|
|
||||||
'affine:page': RootService;
|
'affine:page': RootService;
|
||||||
'affine:database': DatabaseBlockService;
|
'affine:database': DatabaseBlockService;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ export * from './divider-block/index.js';
|
|||||||
export * from './edgeless-text-block/index.js';
|
export * from './edgeless-text-block/index.js';
|
||||||
export * from './frame-block/index.js';
|
export * from './frame-block/index.js';
|
||||||
export * from './latex-block/index.js';
|
export * from './latex-block/index.js';
|
||||||
export * from './note-block/index.js';
|
|
||||||
export { EdgelessTemplatePanel } from './root-block/edgeless/components/toolbar/template/template-panel.js';
|
export { EdgelessTemplatePanel } from './root-block/edgeless/components/toolbar/template/template-panel.js';
|
||||||
export type {
|
export type {
|
||||||
Template,
|
Template,
|
||||||
@@ -52,6 +51,7 @@ export * from '@blocksuite/affine-block-bookmark';
|
|||||||
export * from '@blocksuite/affine-block-embed';
|
export * from '@blocksuite/affine-block-embed';
|
||||||
export * from '@blocksuite/affine-block-image';
|
export * from '@blocksuite/affine-block-image';
|
||||||
export * from '@blocksuite/affine-block-list';
|
export * from '@blocksuite/affine-block-list';
|
||||||
|
export * from '@blocksuite/affine-block-note';
|
||||||
export * from '@blocksuite/affine-block-paragraph';
|
export * from '@blocksuite/affine-block-paragraph';
|
||||||
export * from '@blocksuite/affine-block-surface';
|
export * from '@blocksuite/affine-block-surface';
|
||||||
export {
|
export {
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
export * from './commands/index.js';
|
|
||||||
export * from './note-block.js';
|
|
||||||
export * from './note-edgeless-block.js';
|
|
||||||
export * from './note-service.js';
|
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
|
||||||
import type { BlockComponent, BlockSelection } from '@blocksuite/block-std';
|
|
||||||
import { IS_MAC, IS_WINDOWS } from '@blocksuite/global/env';
|
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
convertSelectedBlocksToLinkedDoc,
|
convertSelectedBlocksToLinkedDoc,
|
||||||
getTitleFromSelectedModels,
|
getTitleFromSelectedModels,
|
||||||
notifyDocCreated,
|
notifyDocCreated,
|
||||||
promptDocTitle,
|
promptDocTitle,
|
||||||
} from '../../_common/utils/render-linked-doc.js';
|
} from '@blocksuite/affine-block-embed';
|
||||||
|
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||||
|
import type { BlockComponent, BlockSelection } from '@blocksuite/block-std';
|
||||||
|
import { IS_MAC, IS_WINDOWS } from '@blocksuite/global/env';
|
||||||
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
|
|
||||||
export class PageKeyboardManager {
|
export class PageKeyboardManager {
|
||||||
private readonly _handleDelete = () => {
|
private readonly _handleDelete = () => {
|
||||||
@@ -117,7 +116,7 @@ export class PageKeyboardManager {
|
|||||||
|
|
||||||
const doc = rootComponent.host.doc;
|
const doc = rootComponent.host.doc;
|
||||||
const autofill = getTitleFromSelectedModels(selectedModels);
|
const autofill = getTitleFromSelectedModels(selectedModels);
|
||||||
promptDocTitle(rootComponent.host, autofill)
|
promptDocTitle(rootComponent.std, autofill)
|
||||||
.then(title => {
|
.then(title => {
|
||||||
if (title === null) return;
|
if (title === null) return;
|
||||||
convertSelectedBlocksToLinkedDoc(
|
convertSelectedBlocksToLinkedDoc(
|
||||||
@@ -126,7 +125,7 @@ export class PageKeyboardManager {
|
|||||||
draftedModels,
|
draftedModels,
|
||||||
title
|
title
|
||||||
).catch(console.error);
|
).catch(console.error);
|
||||||
notifyDocCreated(rootComponent.host, doc);
|
notifyDocCreated(rootComponent.std, doc);
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { NoteBlockComponent } from '@blocksuite/affine-block-note';
|
||||||
import { captureEventTarget } from '@blocksuite/affine-shared/utils';
|
import { captureEventTarget } from '@blocksuite/affine-shared/utils';
|
||||||
import {
|
import {
|
||||||
BLOCK_ID_ATTR,
|
BLOCK_ID_ATTR,
|
||||||
@@ -8,7 +9,6 @@ import {
|
|||||||
import { Point, throttle } from '@blocksuite/global/utils';
|
import { Point, throttle } from '@blocksuite/global/utils';
|
||||||
import { computed } from '@preact/signals-core';
|
import { computed } from '@preact/signals-core';
|
||||||
|
|
||||||
import type { NoteBlockComponent } from '../../../../note-block/index.js';
|
|
||||||
import type { EdgelessRootBlockComponent } from '../../../edgeless/index.js';
|
import type { EdgelessRootBlockComponent } from '../../../edgeless/index.js';
|
||||||
import {
|
import {
|
||||||
DRAG_HANDLE_CONTAINER_WIDTH,
|
DRAG_HANDLE_CONTAINER_WIDTH,
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import type { AttachmentBlockComponent } from '@blocksuite/affine-block-attachment';
|
import type { AttachmentBlockComponent } from '@blocksuite/affine-block-attachment';
|
||||||
import type { BookmarkBlockComponent } from '@blocksuite/affine-block-bookmark';
|
import type { BookmarkBlockComponent } from '@blocksuite/affine-block-bookmark';
|
||||||
import type {
|
import {
|
||||||
EmbedFigmaBlockComponent,
|
type EmbedFigmaBlockComponent,
|
||||||
EmbedGithubBlockComponent,
|
type EmbedGithubBlockComponent,
|
||||||
EmbedLoomBlockComponent,
|
type EmbedLoomBlockComponent,
|
||||||
EmbedYoutubeBlockComponent,
|
type EmbedYoutubeBlockComponent,
|
||||||
|
notifyDocCreated,
|
||||||
|
promptDocTitle,
|
||||||
} from '@blocksuite/affine-block-embed';
|
} from '@blocksuite/affine-block-embed';
|
||||||
import type { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
import type { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
||||||
import { isPeekable, peek } from '@blocksuite/affine-components/peek';
|
import { isPeekable, peek } from '@blocksuite/affine-components/peek';
|
||||||
@@ -30,8 +32,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
createLinkedDocFromEdgelessElements,
|
createLinkedDocFromEdgelessElements,
|
||||||
createLinkedDocFromNote,
|
createLinkedDocFromNote,
|
||||||
notifyDocCreated,
|
|
||||||
promptDocTitle,
|
|
||||||
} from '../../../../_common/utils/render-linked-doc.js';
|
} from '../../../../_common/utils/render-linked-doc.js';
|
||||||
import { duplicate } from '../../../edgeless/utils/clipboard-utils.js';
|
import { duplicate } from '../../../edgeless/utils/clipboard-utils.js';
|
||||||
import { getSortedCloneElements } from '../../../edgeless/utils/clone-utils.js';
|
import { getSortedCloneElements } from '../../../edgeless/utils/clone-utils.js';
|
||||||
@@ -245,11 +245,11 @@ export const conversionsGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
|||||||
label: 'Turn into linked doc',
|
label: 'Turn into linked doc',
|
||||||
type: 'turn-into-linked-doc',
|
type: 'turn-into-linked-doc',
|
||||||
action: async ctx => {
|
action: async ctx => {
|
||||||
const { doc, service, surface, host, std } = ctx;
|
const { doc, service, surface, std } = ctx;
|
||||||
const element = ctx.getNoteBlock();
|
const element = ctx.getNoteBlock();
|
||||||
if (!element) return;
|
if (!element) return;
|
||||||
|
|
||||||
const title = await promptDocTitle(host);
|
const title = await promptDocTitle(std);
|
||||||
if (title === null) return;
|
if (title === null) return;
|
||||||
|
|
||||||
const linkedDoc = createLinkedDocFromNote(doc, element, title);
|
const linkedDoc = createLinkedDocFromNote(doc, element, title);
|
||||||
@@ -309,7 +309,7 @@ export const conversionsGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
|||||||
host,
|
host,
|
||||||
std,
|
std,
|
||||||
}) => {
|
}) => {
|
||||||
const title = await promptDocTitle(host);
|
const title = await promptDocTitle(std);
|
||||||
if (title === null) return;
|
if (title === null) return;
|
||||||
|
|
||||||
const elements = getSortedCloneElements(selection.selectedElements);
|
const elements = getSortedCloneElements(selection.selectedElements);
|
||||||
@@ -360,7 +360,7 @@ export const conversionsGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
|||||||
other: 'new doc',
|
other: 'new doc',
|
||||||
});
|
});
|
||||||
|
|
||||||
notifyDocCreated(host, doc);
|
notifyDocCreated(std, doc);
|
||||||
},
|
},
|
||||||
when: ctx => !(ctx.getLinkedDocBlock() || ctx.getNoteBlock()),
|
when: ctx => !(ctx.getLinkedDocBlock() || ctx.getNoteBlock()),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { whenHover } from '@blocksuite/affine-components/hover';
|
import { whenHover } from '@blocksuite/affine-components/hover';
|
||||||
import { ArrowDownIcon } from '@blocksuite/affine-components/icons';
|
import { ArrowDownIcon } from '@blocksuite/affine-components/icons';
|
||||||
|
import { textConversionConfigs } from '@blocksuite/affine-components/rich-text';
|
||||||
import type { ParagraphBlockModel } from '@blocksuite/affine-model';
|
import type { ParagraphBlockModel } from '@blocksuite/affine-model';
|
||||||
import type { EditorHost } from '@blocksuite/block-std';
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
@@ -8,7 +9,6 @@ import { html } from 'lit';
|
|||||||
import { ref, type RefOrCallback } from 'lit/directives/ref.js';
|
import { ref, type RefOrCallback } from 'lit/directives/ref.js';
|
||||||
import { repeat } from 'lit/directives/repeat.js';
|
import { repeat } from 'lit/directives/repeat.js';
|
||||||
|
|
||||||
import { textConversionConfigs } from '../../../../_common/configs/text-conversion.js';
|
|
||||||
import type { ParagraphActionConfigItem } from '../config.js';
|
import type { ParagraphActionConfigItem } from '../config.js';
|
||||||
import type { AffineFormatBarWidget } from '../format-bar.js';
|
import type { AffineFormatBarWidget } from '../format-bar.js';
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
import {
|
||||||
|
convertSelectedBlocksToLinkedDoc,
|
||||||
|
getTitleFromSelectedModels,
|
||||||
|
notifyDocCreated,
|
||||||
|
promptDocTitle,
|
||||||
|
} from '@blocksuite/affine-block-embed';
|
||||||
import {
|
import {
|
||||||
BoldIcon,
|
BoldIcon,
|
||||||
BulletedListIcon,
|
BulletedListIcon,
|
||||||
@@ -37,12 +43,6 @@ import { assertExists } from '@blocksuite/global/utils';
|
|||||||
import { Slice } from '@blocksuite/store';
|
import { Slice } from '@blocksuite/store';
|
||||||
import { html, type TemplateResult } from 'lit';
|
import { html, type TemplateResult } from 'lit';
|
||||||
|
|
||||||
import {
|
|
||||||
convertSelectedBlocksToLinkedDoc,
|
|
||||||
getTitleFromSelectedModels,
|
|
||||||
notifyDocCreated,
|
|
||||||
promptDocTitle,
|
|
||||||
} from '../../../_common/utils/render-linked-doc.js';
|
|
||||||
import { convertToDatabase } from '../../../database-block/data-source.js';
|
import { convertToDatabase } from '../../../database-block/data-source.js';
|
||||||
import { DATABASE_CONVERT_WHITE_LIST } from '../../../database-block/utils/block-utils.js';
|
import { DATABASE_CONVERT_WHITE_LIST } from '../../../database-block/utils/block-utils.js';
|
||||||
import { FormatBarContext } from './context.js';
|
import { FormatBarContext } from './context.js';
|
||||||
@@ -201,7 +201,7 @@ export function toolbarDefaultConfig(toolbar: AffineFormatBarWidget) {
|
|||||||
})
|
})
|
||||||
.draftSelectedModels()
|
.draftSelectedModels()
|
||||||
.run();
|
.run();
|
||||||
const { draftedModels, selectedModels } = ctx;
|
const { draftedModels, selectedModels, std } = ctx;
|
||||||
if (!selectedModels?.length || !draftedModels) return;
|
if (!selectedModels?.length || !draftedModels) return;
|
||||||
|
|
||||||
const host = formatBar.host;
|
const host = formatBar.host;
|
||||||
@@ -209,16 +209,16 @@ export function toolbarDefaultConfig(toolbar: AffineFormatBarWidget) {
|
|||||||
|
|
||||||
const doc = host.doc;
|
const doc = host.doc;
|
||||||
const autofill = getTitleFromSelectedModels(selectedModels);
|
const autofill = getTitleFromSelectedModels(selectedModels);
|
||||||
promptDocTitle(host, autofill)
|
promptDocTitle(std, autofill)
|
||||||
.then(async title => {
|
.then(async title => {
|
||||||
if (title === null) return;
|
if (title === null) return;
|
||||||
await convertSelectedBlocksToLinkedDoc(
|
await convertSelectedBlocksToLinkedDoc(
|
||||||
host.std,
|
std,
|
||||||
doc,
|
doc,
|
||||||
draftedModels,
|
draftedModels,
|
||||||
title
|
title
|
||||||
);
|
);
|
||||||
notifyDocCreated(host, doc);
|
notifyDocCreated(std, doc);
|
||||||
host.std.getOptional(TelemetryProvider)?.track('DocCreated', {
|
host.std.getOptional(TelemetryProvider)?.track('DocCreated', {
|
||||||
control: 'create linked doc',
|
control: 'create linked doc',
|
||||||
page: 'doc editor',
|
page: 'doc editor',
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
getInlineEditorByModel,
|
getInlineEditorByModel,
|
||||||
insertContent,
|
insertContent,
|
||||||
REFERENCE_NODE,
|
REFERENCE_NODE,
|
||||||
|
textConversionConfigs,
|
||||||
textFormatConfigs,
|
textFormatConfigs,
|
||||||
} from '@blocksuite/affine-components/rich-text';
|
} from '@blocksuite/affine-components/rich-text';
|
||||||
import { toast } from '@blocksuite/affine-components/toast';
|
import { toast } from '@blocksuite/affine-components/toast';
|
||||||
@@ -49,7 +50,6 @@ import { Slice, Text } from '@blocksuite/store';
|
|||||||
import type { TemplateResult } from 'lit';
|
import type { TemplateResult } from 'lit';
|
||||||
|
|
||||||
import { toggleEmbedCardCreateModal } from '../../../_common/components/embed-card/modal/embed-card-create-modal.js';
|
import { toggleEmbedCardCreateModal } from '../../../_common/components/embed-card/modal/embed-card-create-modal.js';
|
||||||
import { textConversionConfigs } from '../../../_common/configs/text-conversion.js';
|
|
||||||
import type { DataViewBlockComponent } from '../../../data-view-block/index.js';
|
import type { DataViewBlockComponent } from '../../../data-view-block/index.js';
|
||||||
import { getSurfaceBlock } from '../../../surface-ref-block/utils.js';
|
import { getSurfaceBlock } from '../../../surface-ref-block/utils.js';
|
||||||
import type { RootBlockComponent } from '../../types.js';
|
import type { RootBlockComponent } from '../../types.js';
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import type { TextFormatConfig } from '@blocksuite/affine-components/rich-text';
|
import type {
|
||||||
|
TextConversionConfig,
|
||||||
|
TextFormatConfig,
|
||||||
|
} from '@blocksuite/affine-components/rich-text';
|
||||||
import { isInsideBlockByFlavour } from '@blocksuite/affine-shared/utils';
|
import { isInsideBlockByFlavour } from '@blocksuite/affine-shared/utils';
|
||||||
import { assertType } from '@blocksuite/global/utils';
|
import { assertType } from '@blocksuite/global/utils';
|
||||||
import type { BlockModel } from '@blocksuite/store';
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
import type { TextConversionConfig } from '../../../_common/configs/text-conversion.js';
|
|
||||||
import type {
|
import type {
|
||||||
SlashMenuActionItem,
|
SlashMenuActionItem,
|
||||||
SlashMenuContext,
|
SlashMenuContext,
|
||||||
|
|||||||
@@ -37,6 +37,9 @@
|
|||||||
{
|
{
|
||||||
"path": "../affine/block-embed"
|
"path": "../affine/block-embed"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "../affine/block-note"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "../affine/block-bookmark"
|
"path": "../affine/block-bookmark"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -81,6 +81,20 @@ export const PackageList = [
|
|||||||
'blocksuite/framework/store',
|
'blocksuite/framework/store',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
location: 'blocksuite/affine/block-note',
|
||||||
|
name: '@blocksuite/affine-block-note',
|
||||||
|
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-paragraph',
|
location: 'blocksuite/affine/block-paragraph',
|
||||||
name: '@blocksuite/affine-block-paragraph',
|
name: '@blocksuite/affine-block-paragraph',
|
||||||
@@ -170,6 +184,7 @@ export const PackageList = [
|
|||||||
'blocksuite/affine/block-embed',
|
'blocksuite/affine/block-embed',
|
||||||
'blocksuite/affine/block-image',
|
'blocksuite/affine/block-image',
|
||||||
'blocksuite/affine/block-list',
|
'blocksuite/affine/block-list',
|
||||||
|
'blocksuite/affine/block-note',
|
||||||
'blocksuite/affine/block-paragraph',
|
'blocksuite/affine/block-paragraph',
|
||||||
'blocksuite/affine/block-surface',
|
'blocksuite/affine/block-surface',
|
||||||
'blocksuite/affine/components',
|
'blocksuite/affine/components',
|
||||||
@@ -506,6 +521,7 @@ export type PackageName =
|
|||||||
| '@blocksuite/affine-block-embed'
|
| '@blocksuite/affine-block-embed'
|
||||||
| '@blocksuite/affine-block-image'
|
| '@blocksuite/affine-block-image'
|
||||||
| '@blocksuite/affine-block-list'
|
| '@blocksuite/affine-block-list'
|
||||||
|
| '@blocksuite/affine-block-note'
|
||||||
| '@blocksuite/affine-block-paragraph'
|
| '@blocksuite/affine-block-paragraph'
|
||||||
| '@blocksuite/affine-block-surface'
|
| '@blocksuite/affine-block-surface'
|
||||||
| '@blocksuite/affine-components'
|
| '@blocksuite/affine-components'
|
||||||
|
|||||||
24
yarn.lock
24
yarn.lock
@@ -3340,6 +3340,29 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
"@blocksuite/affine-block-note@workspace:*, @blocksuite/affine-block-note@workspace:blocksuite/affine/block-note":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@blocksuite/affine-block-note@workspace:blocksuite/affine/block-note"
|
||||||
|
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"
|
||||||
|
lit: "npm:^3.2.0"
|
||||||
|
minimatch: "npm:^10.0.1"
|
||||||
|
zod: "npm:^3.23.8"
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"@blocksuite/affine-block-paragraph@workspace:*, @blocksuite/affine-block-paragraph@workspace:blocksuite/affine/block-paragraph":
|
"@blocksuite/affine-block-paragraph@workspace:*, @blocksuite/affine-block-paragraph@workspace:blocksuite/affine/block-paragraph":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@blocksuite/affine-block-paragraph@workspace:blocksuite/affine/block-paragraph"
|
resolution: "@blocksuite/affine-block-paragraph@workspace:blocksuite/affine/block-paragraph"
|
||||||
@@ -3511,6 +3534,7 @@ __metadata:
|
|||||||
"@blocksuite/affine-block-embed": "workspace:*"
|
"@blocksuite/affine-block-embed": "workspace:*"
|
||||||
"@blocksuite/affine-block-image": "workspace:*"
|
"@blocksuite/affine-block-image": "workspace:*"
|
||||||
"@blocksuite/affine-block-list": "workspace:*"
|
"@blocksuite/affine-block-list": "workspace:*"
|
||||||
|
"@blocksuite/affine-block-note": "workspace:*"
|
||||||
"@blocksuite/affine-block-paragraph": "workspace:*"
|
"@blocksuite/affine-block-paragraph": "workspace:*"
|
||||||
"@blocksuite/affine-block-surface": "workspace:*"
|
"@blocksuite/affine-block-surface": "workspace:*"
|
||||||
"@blocksuite/affine-components": "workspace:*"
|
"@blocksuite/affine-components": "workspace:*"
|
||||||
|
|||||||
Reference in New Issue
Block a user