mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
feat: add @affine/bookmark-block plugin (#2618)
This commit is contained in:
@@ -11,6 +11,7 @@ import { useBlockSuiteWorkspacePageTitle } from '@toeverything/hooks/use-block-s
|
|||||||
import { affinePluginsAtom } from '@toeverything/plugin-infra/manager';
|
import { affinePluginsAtom } from '@toeverything/plugin-infra/manager';
|
||||||
import type { PluginUIAdapter } from '@toeverything/plugin-infra/type';
|
import type { PluginUIAdapter } from '@toeverything/plugin-infra/type';
|
||||||
import type { ExpectedLayout } from '@toeverything/plugin-infra/type';
|
import type { ExpectedLayout } from '@toeverything/plugin-infra/type';
|
||||||
|
import type { PluginBlockSuiteAdapter } from '@toeverything/plugin-infra/type';
|
||||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
@@ -50,6 +51,11 @@ const EditorWrapper = memo(function EditorWrapper({
|
|||||||
onLoad,
|
onLoad,
|
||||||
isPublic,
|
isPublic,
|
||||||
}: PageDetailEditorProps) {
|
}: PageDetailEditorProps) {
|
||||||
|
const affinePluginsMap = useAtomValue(affinePluginsAtom);
|
||||||
|
const plugins = useMemo(
|
||||||
|
() => Object.values(affinePluginsMap),
|
||||||
|
[affinePluginsMap]
|
||||||
|
);
|
||||||
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;
|
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;
|
||||||
const page = useBlockSuiteWorkspacePage(blockSuiteWorkspace, pageId);
|
const page = useBlockSuiteWorkspacePage(blockSuiteWorkspace, pageId);
|
||||||
if (!page) {
|
if (!page) {
|
||||||
@@ -88,12 +94,22 @@ const EditorWrapper = memo(function EditorWrapper({
|
|||||||
updatedDate: Date.now(),
|
updatedDate: Date.now(),
|
||||||
});
|
});
|
||||||
localStorage.setItem('last_page_id', page.id);
|
localStorage.setItem('last_page_id', page.id);
|
||||||
|
let dispose = () => {};
|
||||||
if (onLoad) {
|
if (onLoad) {
|
||||||
return onLoad(page, editor);
|
dispose = onLoad(page, editor);
|
||||||
}
|
}
|
||||||
return () => {};
|
const uiDecorators = plugins
|
||||||
|
.map(plugin => plugin.blockSuiteAdapter.uiDecorator)
|
||||||
|
.filter((ui): ui is PluginBlockSuiteAdapter['uiDecorator'] =>
|
||||||
|
Boolean(ui)
|
||||||
|
);
|
||||||
|
const disposes = uiDecorators.map(ui => ui(editor));
|
||||||
|
return () => {
|
||||||
|
disposes.map(fn => fn());
|
||||||
|
dispose();
|
||||||
|
};
|
||||||
},
|
},
|
||||||
[onLoad, setEditor]
|
[plugins, onLoad, setEditor]
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,14 +16,6 @@ import {
|
|||||||
blockSuiteEditorHeaderStyle,
|
blockSuiteEditorHeaderStyle,
|
||||||
blockSuiteEditorStyle,
|
blockSuiteEditorStyle,
|
||||||
} from './index.css';
|
} from './index.css';
|
||||||
import { bookmarkPlugin } from './plugins/bookmark';
|
|
||||||
|
|
||||||
export type EditorPlugin = {
|
|
||||||
flavour: string;
|
|
||||||
onInit?: (page: Page, editor: Readonly<EditorContainer>) => void;
|
|
||||||
onLoad?: (page: Page, editor: EditorContainer) => () => void;
|
|
||||||
render?: (props: { page: Page }) => ReactElement | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type EditorProps = {
|
export type EditorProps = {
|
||||||
page: Page;
|
page: Page;
|
||||||
@@ -50,9 +42,6 @@ const ImagePreviewModal = lazy(() =>
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
// todo(himself65): plugin-infra should support this
|
|
||||||
const plugins = [bookmarkPlugin];
|
|
||||||
|
|
||||||
const BlockSuiteEditorImpl = (props: EditorProps): ReactElement => {
|
const BlockSuiteEditorImpl = (props: EditorProps): ReactElement => {
|
||||||
const { onLoad, page, mode, style, onInit } = props;
|
const { onLoad, page, mode, style, onInit } = props;
|
||||||
const JotaiEditorContainer = useAtomValue(
|
const JotaiEditorContainer = useAtomValue(
|
||||||
@@ -77,9 +66,6 @@ const BlockSuiteEditorImpl = (props: EditorProps): ReactElement => {
|
|||||||
editor.page = page;
|
editor.page = page;
|
||||||
if (page.root === null) {
|
if (page.root === null) {
|
||||||
onInit(page, editor);
|
onInit(page, editor);
|
||||||
plugins.forEach(plugin => {
|
|
||||||
plugin.onInit?.(page, editor);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [editor, page, onInit]);
|
}, [editor, page, onInit]);
|
||||||
@@ -88,7 +74,6 @@ const BlockSuiteEditorImpl = (props: EditorProps): ReactElement => {
|
|||||||
if (editor.page && onLoad) {
|
if (editor.page && onLoad) {
|
||||||
const disposes = [] as ((() => void) | undefined)[];
|
const disposes = [] as ((() => void) | undefined)[];
|
||||||
disposes.push(onLoad?.(page, editor));
|
disposes.push(onLoad?.(page, editor));
|
||||||
disposes.push(...plugins.map(plugin => plugin.onLoad?.(page, editor)));
|
|
||||||
return () => {
|
return () => {
|
||||||
disposes
|
disposes
|
||||||
.filter((dispose): dispose is () => void => !!dispose)
|
.filter((dispose): dispose is () => void => !!dispose)
|
||||||
@@ -201,12 +186,6 @@ export const BlockSuiteEditor = memo(function BlockSuiteEditor(
|
|||||||
)}
|
)}
|
||||||
</Suspense>
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
{plugins.map(plugin => {
|
|
||||||
const Renderer = plugin.render;
|
|
||||||
return Renderer ? (
|
|
||||||
<Renderer page={props.page} key={plugin.flavour} />
|
|
||||||
) : null;
|
|
||||||
})}
|
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
10
packages/env/src/bootstrap.ts
vendored
10
packages/env/src/bootstrap.ts
vendored
@@ -1,7 +1,11 @@
|
|||||||
import { config, getEnvironment, setupGlobal } from './config';
|
import { config, setupGlobal } from './config';
|
||||||
|
|
||||||
if (config.enablePlugin && !getEnvironment().isServer) {
|
setupGlobal();
|
||||||
|
|
||||||
|
if (config.enablePlugin && !environment.isServer) {
|
||||||
import('@affine/copilot');
|
import('@affine/copilot');
|
||||||
}
|
}
|
||||||
|
|
||||||
setupGlobal();
|
if (!environment.isServer) {
|
||||||
|
import('@affine/bookmark-block');
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,12 +12,22 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@affine/component": "workspace:*",
|
"@affine/component": "workspace:*",
|
||||||
"@affine/env": "workspace:*",
|
"@affine/env": "workspace:*",
|
||||||
"@affine/workspace": "workspace:*"
|
"@affine/workspace": "workspace:*",
|
||||||
|
"@blocksuite/blocks": "0.0.0-20230531080915-ca9c55a2-nightly",
|
||||||
|
"@blocksuite/editor": "0.0.0-20230531080915-ca9c55a2-nightly",
|
||||||
|
"@blocksuite/global": "0.0.0-20230531080915-ca9c55a2-nightly",
|
||||||
|
"@blocksuite/lit": "0.0.0-20230531080915-ca9c55a2-nightly",
|
||||||
|
"@blocksuite/store": "0.0.0-20230531080915-ca9c55a2-nightly"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"jotai": "^2.1.0"
|
"jotai": "^2.1.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
"@blocksuite/blocks": "*",
|
||||||
|
"@blocksuite/editor": "*",
|
||||||
|
"@blocksuite/global": "*",
|
||||||
|
"@blocksuite/lit": "*",
|
||||||
|
"@blocksuite/store": "*",
|
||||||
"jotai": "*",
|
"jotai": "*",
|
||||||
"react": "*",
|
"react": "*",
|
||||||
"react-dom": "*"
|
"react-dom": "*"
|
||||||
|
|||||||
@@ -4,27 +4,53 @@ import { atom } from 'jotai';
|
|||||||
|
|
||||||
import type { AffinePlugin, Definition } from './type';
|
import type { AffinePlugin, Definition } from './type';
|
||||||
import type { Loader, PluginUIAdapter } from './type';
|
import type { Loader, PluginUIAdapter } from './type';
|
||||||
|
import type { PluginBlockSuiteAdapter } from './type';
|
||||||
|
|
||||||
// todo: for now every plugin is enabled by default
|
// todo: for now every plugin is enabled by default
|
||||||
export const affinePluginsAtom = atom<Record<string, AffinePlugin<string>>>({});
|
export const affinePluginsAtom = atom<Record<string, AffinePlugin<string>>>({});
|
||||||
|
|
||||||
const pluginLogger = new DebugLogger('affine:plugin');
|
const pluginLogger = new DebugLogger('affine:plugin');
|
||||||
import { config } from '@affine/env';
|
|
||||||
export function definePlugin<ID extends string>(
|
export function definePlugin<ID extends string>(
|
||||||
definition: Definition<ID>,
|
definition: Definition<ID>,
|
||||||
uiAdapterLoader?: Loader<Partial<PluginUIAdapter>>
|
uiAdapterLoader?: Loader<Partial<PluginUIAdapter>>,
|
||||||
|
blockSuiteAdapter?: Loader<Partial<PluginBlockSuiteAdapter>>
|
||||||
) {
|
) {
|
||||||
if (!config.enablePlugin) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const basePlugin = {
|
const basePlugin = {
|
||||||
definition,
|
definition,
|
||||||
uiAdapter: {},
|
uiAdapter: {},
|
||||||
|
blockSuiteAdapter: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
rootStore.set(affinePluginsAtom, plugins => ({
|
rootStore.set(affinePluginsAtom, plugins => ({
|
||||||
...plugins,
|
...plugins,
|
||||||
[definition.id]: basePlugin,
|
[definition.id]: basePlugin,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (blockSuiteAdapter) {
|
||||||
|
const updateAdapter = (adapter: Partial<PluginBlockSuiteAdapter>) => {
|
||||||
|
rootStore.set(affinePluginsAtom, plugins => ({
|
||||||
|
...plugins,
|
||||||
|
[definition.id]: {
|
||||||
|
...basePlugin,
|
||||||
|
blockSuiteAdapter: adapter,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
blockSuiteAdapter
|
||||||
|
.load()
|
||||||
|
.then(({ default: adapter }) => updateAdapter(adapter));
|
||||||
|
|
||||||
|
if (import.meta.webpackHot) {
|
||||||
|
blockSuiteAdapter.hotModuleReload(async _ => {
|
||||||
|
const adapter = (await _).default;
|
||||||
|
updateAdapter(adapter);
|
||||||
|
pluginLogger.info('[HMR] Plugin', definition.id, 'hot reloaded.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (uiAdapterLoader) {
|
if (uiAdapterLoader) {
|
||||||
const updateAdapter = (adapter: Partial<PluginUIAdapter>) => {
|
const updateAdapter = (adapter: Partial<PluginUIAdapter>) => {
|
||||||
rootStore.set(affinePluginsAtom, plugins => ({
|
rootStore.set(affinePluginsAtom, plugins => ({
|
||||||
@@ -39,6 +65,7 @@ export function definePlugin<ID extends string>(
|
|||||||
uiAdapterLoader
|
uiAdapterLoader
|
||||||
.load()
|
.load()
|
||||||
.then(({ default: adapter }) => updateAdapter(adapter));
|
.then(({ default: adapter }) => updateAdapter(adapter));
|
||||||
|
|
||||||
if (import.meta.webpackHot) {
|
if (import.meta.webpackHot) {
|
||||||
uiAdapterLoader.hotModuleReload(async _ => {
|
uiAdapterLoader.hotModuleReload(async _ => {
|
||||||
const adapter = (await _).default;
|
const adapter = (await _).default;
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
* AFFiNE Plugin System Types
|
* AFFiNE Plugin System Types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { EditorContainer } from '@blocksuite/editor';
|
||||||
|
import type { Workspace } from '@blocksuite/store';
|
||||||
|
import type { Page } from '@playwright/test';
|
||||||
import type { WritableAtom } from 'jotai';
|
import type { WritableAtom } from 'jotai';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import type { MosaicDirection, MosaicNode } from 'react-mosaic-component';
|
import type { MosaicDirection, MosaicNode } from 'react-mosaic-component';
|
||||||
@@ -152,6 +155,14 @@ export type PluginUIAdapter = {
|
|||||||
debugContent: Adapter<Record<string, unknown>>;
|
debugContent: Adapter<Record<string, unknown>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Cleanup = () => void;
|
||||||
|
|
||||||
|
export type PluginBlockSuiteAdapter = {
|
||||||
|
storeDecorator: (currentWorkspace: Workspace) => Promise<void>;
|
||||||
|
pageDecorator: (currentPage: Page) => Cleanup;
|
||||||
|
uiDecorator: (root: EditorContainer) => Cleanup;
|
||||||
|
};
|
||||||
|
|
||||||
export type PluginAdapterCreator = (
|
export type PluginAdapterCreator = (
|
||||||
context: AffinePluginContext
|
context: AffinePluginContext
|
||||||
) => PluginUIAdapter;
|
) => PluginUIAdapter;
|
||||||
@@ -159,4 +170,5 @@ export type PluginAdapterCreator = (
|
|||||||
export type AffinePlugin<ID extends string> = {
|
export type AffinePlugin<ID extends string> = {
|
||||||
definition: Definition<ID>;
|
definition: Definition<ID>;
|
||||||
uiAdapter: Partial<PluginUIAdapter>;
|
uiAdapter: Partial<PluginUIAdapter>;
|
||||||
|
blockSuiteAdapter: Partial<PluginBlockSuiteAdapter>;
|
||||||
};
|
};
|
||||||
|
|||||||
5
plugins/bookmark-block/README.md
Normal file
5
plugins/bookmark-block/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# `@affine/bookmark-block`
|
||||||
|
|
||||||
|
> A block for bookmarking a website
|
||||||
|
|
||||||
|

|
||||||
BIN
plugins/bookmark-block/assets/preview.png
Normal file
BIN
plugins/bookmark-block/assets/preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
20
plugins/bookmark-block/package.json
Normal file
20
plugins/bookmark-block/package.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "@affine/bookmark-block",
|
||||||
|
"private": true,
|
||||||
|
"main": "./src/index.ts",
|
||||||
|
"module": "./src/index.ts",
|
||||||
|
"exports": {
|
||||||
|
".": "./src/index.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@toeverything/plugin-infra": "workspace:*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"react": "18.3.0-canary-16d053d59-20230506",
|
||||||
|
"react-dom": "18.3.0-canary-16d053d59-20230506"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*",
|
||||||
|
"react-dom": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
29
plugins/bookmark-block/src/blocksuite/index.tsx
Normal file
29
plugins/bookmark-block/src/blocksuite/index.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import type { PluginBlockSuiteAdapter } from '@toeverything/plugin-infra/type';
|
||||||
|
import { StrictMode } from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
|
import { BookMarkUI } from './ui';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
uiDecorator: editor => {
|
||||||
|
if (
|
||||||
|
editor.parentElement &&
|
||||||
|
editor.page.awarenessStore.getFlag('enable_bookmark_operation')
|
||||||
|
) {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
editor.parentElement.appendChild(div);
|
||||||
|
const root = createRoot(div);
|
||||||
|
root.render(
|
||||||
|
<StrictMode>
|
||||||
|
<BookMarkUI page={editor.page} />
|
||||||
|
</StrictMode>
|
||||||
|
);
|
||||||
|
return () => {
|
||||||
|
root.unmount();
|
||||||
|
div.remove();
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
} satisfies Partial<PluginBlockSuiteAdapter>;
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { MenuItem, PureMenu } from '@affine/component';
|
||||||
|
import { MuiClickAwayListener } from '@affine/component';
|
||||||
import type { SerializedBlock } from '@blocksuite/blocks';
|
import type { SerializedBlock } from '@blocksuite/blocks';
|
||||||
import {
|
import {
|
||||||
getCurrentBlockRange,
|
getCurrentBlockRange,
|
||||||
@@ -6,14 +8,17 @@ import {
|
|||||||
} from '@blocksuite/blocks/std';
|
} from '@blocksuite/blocks/std';
|
||||||
import type { Page } from '@blocksuite/store';
|
import type { Page } from '@blocksuite/store';
|
||||||
import { assertExists } from '@blocksuite/store';
|
import { assertExists } from '@blocksuite/store';
|
||||||
|
import type { FC } from 'react';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { MenuItem, MuiClickAwayListener, PureMenu } from '../../..';
|
export type BookMarkProps = {
|
||||||
import type { EditorPlugin } from '..';
|
page: Page;
|
||||||
|
};
|
||||||
|
|
||||||
type ShortcutMap = {
|
type ShortcutMap = {
|
||||||
[key: string]: (e: KeyboardEvent, page: Page) => void;
|
[key: string]: (e: KeyboardEvent, page: Page) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const menuOptions = [
|
const menuOptions = [
|
||||||
{
|
{
|
||||||
id: 'dismiss',
|
id: 'dismiss',
|
||||||
@@ -90,7 +95,7 @@ const shouldShowBookmarkMenu = (pastedBlocks: SerializedBlock[]) => {
|
|||||||
}
|
}
|
||||||
return !!firstBlock.text[0].attributes?.link;
|
return !!firstBlock.text[0].attributes?.link;
|
||||||
};
|
};
|
||||||
const BookMarkMenu: EditorPlugin['render'] = ({ page }) => {
|
export const BookMarkUI: FC<BookMarkProps> = ({ page }) => {
|
||||||
const [anchor, setAnchor] = useState<Range | null>(null);
|
const [anchor, setAnchor] = useState<Range | null>(null);
|
||||||
const [selectedOption, setSelectedOption] = useState<string>(
|
const [selectedOption, setSelectedOption] = useState<string>(
|
||||||
menuOptions[0].id
|
menuOptions[0].id
|
||||||
@@ -213,13 +218,3 @@ const BookMarkMenu: EditorPlugin['render'] = ({ page }) => {
|
|||||||
</MuiClickAwayListener>
|
</MuiClickAwayListener>
|
||||||
) : null;
|
) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Defender: EditorPlugin['render'] = props => {
|
|
||||||
const flag = props.page.awarenessStore.getFlag('enable_bookmark_operation');
|
|
||||||
return flag ? <BookMarkMenu {...props} /> : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const bookmarkPlugin: EditorPlugin = {
|
|
||||||
flavour: 'bookmark',
|
|
||||||
render: Defender,
|
|
||||||
};
|
|
||||||
32
plugins/bookmark-block/src/index.ts
Normal file
32
plugins/bookmark-block/src/index.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { definePlugin } from '@toeverything/plugin-infra/manager';
|
||||||
|
import { ReleaseStage } from '@toeverything/plugin-infra/type';
|
||||||
|
|
||||||
|
definePlugin(
|
||||||
|
{
|
||||||
|
id: 'com.blocksuite.bookmark-block',
|
||||||
|
name: {
|
||||||
|
fallback: 'BlockSuite Bookmark Block',
|
||||||
|
i18nKey: 'com.blocksuite.bookmark.name',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
fallback: 'Bookmark block',
|
||||||
|
},
|
||||||
|
publisher: {
|
||||||
|
name: {
|
||||||
|
fallback: 'AFFiNE',
|
||||||
|
},
|
||||||
|
link: 'https://affine.pro',
|
||||||
|
},
|
||||||
|
stage: ReleaseStage.NIGHTLY,
|
||||||
|
version: '0.0.1',
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
load: () => import('./blocksuite/index'),
|
||||||
|
hotModuleReload: onHot =>
|
||||||
|
import.meta.webpackHot &&
|
||||||
|
import.meta.webpackHot.accept('./blocksuite', () =>
|
||||||
|
onHot(import('./blocksuite/index'))
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
4
plugins/bookmark-block/tsconfig.json
Normal file
4
plugins/bookmark-block/tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"include": ["./src"]
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import { atom } from 'jotai';
|
|
||||||
|
|
||||||
export const contentExpandAtom = atom(false);
|
|
||||||
23
yarn.lock
23
yarn.lock
@@ -30,6 +30,19 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
"@affine/bookmark-block@workspace:plugins/bookmark-block":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@affine/bookmark-block@workspace:plugins/bookmark-block"
|
||||||
|
dependencies:
|
||||||
|
"@toeverything/plugin-infra": "workspace:*"
|
||||||
|
react: 18.3.0-canary-16d053d59-20230506
|
||||||
|
react-dom: 18.3.0-canary-16d053d59-20230506
|
||||||
|
peerDependencies:
|
||||||
|
react: "*"
|
||||||
|
react-dom: "*"
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"@affine/cli@workspace:*, @affine/cli@workspace:packages/cli":
|
"@affine/cli@workspace:*, @affine/cli@workspace:packages/cli":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@affine/cli@workspace:packages/cli"
|
resolution: "@affine/cli@workspace:packages/cli"
|
||||||
@@ -9087,8 +9100,18 @@ __metadata:
|
|||||||
"@affine/component": "workspace:*"
|
"@affine/component": "workspace:*"
|
||||||
"@affine/env": "workspace:*"
|
"@affine/env": "workspace:*"
|
||||||
"@affine/workspace": "workspace:*"
|
"@affine/workspace": "workspace:*"
|
||||||
|
"@blocksuite/blocks": 0.0.0-20230531080915-ca9c55a2-nightly
|
||||||
|
"@blocksuite/editor": 0.0.0-20230531080915-ca9c55a2-nightly
|
||||||
|
"@blocksuite/global": 0.0.0-20230531080915-ca9c55a2-nightly
|
||||||
|
"@blocksuite/lit": 0.0.0-20230531080915-ca9c55a2-nightly
|
||||||
|
"@blocksuite/store": 0.0.0-20230531080915-ca9c55a2-nightly
|
||||||
jotai: ^2.1.0
|
jotai: ^2.1.0
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
"@blocksuite/blocks": "*"
|
||||||
|
"@blocksuite/editor": "*"
|
||||||
|
"@blocksuite/global": "*"
|
||||||
|
"@blocksuite/lit": "*"
|
||||||
|
"@blocksuite/store": "*"
|
||||||
jotai: "*"
|
jotai: "*"
|
||||||
react: "*"
|
react: "*"
|
||||||
react-dom: "*"
|
react-dom: "*"
|
||||||
|
|||||||
Reference in New Issue
Block a user