feat: split components (#1530)

This commit is contained in:
Himself65
2023-03-10 23:15:19 -06:00
committed by GitHub
parent a795000363
commit 9a04a1e34f
23 changed files with 1925 additions and 130 deletions

View File

@@ -0,0 +1,83 @@
/* deepscan-disable USELESS_ARROW_FUNC_BIND */
import { __unstableSchemas, builtInSchemas } from '@blocksuite/blocks/models';
import { EditorContainer } from '@blocksuite/editor';
import { Page, Workspace } from '@blocksuite/store';
import { expect } from '@storybook/jest';
import { Meta, StoryFn } from '@storybook/react';
import { useEffect, useState } from 'react';
import { BlockSuiteEditor, EditorProps } from '.';
function initPage(page: Page, editor: Readonly<EditorContainer>): void {
// Add page block and surface block at root level
const pageBlockId = page.addBlockByFlavour('affine:page', {
title: new page.Text(''),
});
page.addBlockByFlavour('affine:surface', {}, null);
const frameId = page.addBlockByFlavour('affine:frame', {}, pageBlockId);
page.addBlockByFlavour('affine:paragraph', {}, frameId);
page.resetHistory();
}
const blockSuiteWorkspace = new Workspace({
id: 'test',
blobOptionsGetter: () => void 0,
});
blockSuiteWorkspace.register(builtInSchemas).register(__unstableSchemas);
const promise = new Promise<void>(resolve => {
blockSuiteWorkspace.slots.pageAdded.once(() => {
resolve();
});
});
blockSuiteWorkspace.createPage('page0');
type BlockSuiteMeta = Meta<typeof BlockSuiteEditor>;
export default {
title: 'BlockSuite/Editor',
component: BlockSuiteEditor,
} satisfies BlockSuiteMeta;
const Template: StoryFn<EditorProps> = (args: EditorProps) => {
const [loaded, setLoaded] = useState(false);
const page = blockSuiteWorkspace.getPage('page0');
useEffect(() => {
promise
.then(() => setLoaded(true))
.then(() => {
document.dispatchEvent(new Event('blocksuite:ready'));
});
}, []);
if (!loaded || !page) return <div>Loading...</div>;
return (
<BlockSuiteEditor
{...args}
blockSuiteWorkspace={blockSuiteWorkspace}
page={page}
/>
);
};
export const Empty = Template.bind({});
Empty.play = async ({ canvasElement }) => {
await new Promise<void>(resolve => {
document.addEventListener('blocksuite:ready', () => resolve(), {
once: true,
});
});
const editorContainer = canvasElement.querySelector(
'[data-testid="editor-test-page0"]'
) as HTMLDivElement;
expect(editorContainer).not.toBeNull();
await new Promise<void>(resolve => {
setTimeout(() => resolve(), 50);
});
const editor = editorContainer.querySelector(
'editor-container'
) as EditorContainer;
expect(editor).not.toBeNull();
};
Empty.args = {
onInit: initPage,
mode: 'page',
};

View File

@@ -0,0 +1,94 @@
import { BlockHub } from '@blocksuite/blocks';
import { EditorContainer } from '@blocksuite/editor';
import type { Page, Workspace } from '@blocksuite/store';
import { CSSProperties, useEffect, useRef } from 'react';
export type EditorProps = {
blockSuiteWorkspace: Workspace;
page: Page;
mode: 'page' | 'edgeless';
onInit: (page: Page, editor: Readonly<EditorContainer>) => void;
onLoad?: (page: Page, editor: EditorContainer) => void;
style?: CSSProperties;
};
declare global {
// eslint-disable-next-line no-var
var currentBlockSuiteWorkspace: Workspace | undefined;
// eslint-disable-next-line no-var
var currentPage: Page | undefined;
// eslint-disable-next-line no-var
var currentEditor: EditorContainer | undefined;
}
export const BlockSuiteEditor = (props: EditorProps) => {
const page = props.page;
const editorRef = useRef<EditorContainer | null>(null);
const blockHubRef = useRef<BlockHub | null>(null);
if (editorRef.current === null) {
editorRef.current = new EditorContainer();
globalThis.currentEditor = editorRef.current;
}
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (editorRef.current) {
editorRef.current.mode = props.mode;
}
}, [props.mode]);
useEffect(() => {
const editor = editorRef.current;
if (!editor || !ref.current || !page) {
return;
}
editor.page = page;
if (page.root === null) {
props.onInit(page, editor);
}
props.onLoad?.(page, editor);
return;
}, [page, props]);
useEffect(() => {
const editor = editorRef.current;
const container = ref.current;
if (!editor || !container || !page) {
return;
}
if (
page.awarenessStore.getFlag('enable_block_hub') &&
props.mode === 'page'
) {
editor.createBlockHub().then(blockHub => {
if (blockHubRef.current) {
blockHubRef.current.remove();
}
blockHubRef.current = blockHub;
const toolWrapper = document.querySelector('#toolWrapper');
if (!toolWrapper) {
console.warn(
'toolWrapper not found, block hub feature will not be available.'
);
} else {
toolWrapper.appendChild(blockHub);
}
});
}
container.appendChild(editor);
return () => {
blockHubRef.current?.remove();
container.removeChild(editor);
};
}, [page, props.mode]);
return (
<div
data-testid={`editor-${props.blockSuiteWorkspace.id}-${props.page.id}`}
className="editor-wrapper"
style={props.style}
ref={ref}
/>
);
};

View File

@@ -1,4 +1,3 @@
// export * from './components/BlockSuiteEditor';
export * from './components/ListSkeleton';
export * from './styles';
export * from './ui/breadcrumbs';

View File

@@ -1,20 +1,33 @@
/* deepscan-disable USELESS_ARROW_FUNC_BIND */
import { Link, Typography } from '@mui/material';
import { Meta, Story } from '@storybook/react';
import { expect } from '@storybook/jest';
import { Meta, StoryFn } from '@storybook/react';
import { within } from '@storybook/testing-library';
import { Breadcrumbs } from '..';
export default {
title: 'AFFiNE/Breadcrumbs',
component: Breadcrumbs,
} as Meta;
} as Meta<typeof Breadcrumbs>;
const Template: Story = args => <Breadcrumbs {...args} />;
const Template: StoryFn = args => <Breadcrumbs {...args} />;
export const Primary = Template.bind(undefined);
Primary.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
const text = canvas.getByText('AFFiNE');
expect(text.getAttribute('data-testid')).toBe('affine');
};
Primary.args = {
children: [
<Link key="1" underline="hover" color="inherit" href="/">
<Link
data-testid="affine"
key="1"
underline="hover"
color="inherit"
href="/"
>
AFFiNE
</Link>,
<Link key="2" underline="hover" color="inherit" href="/Docs/">

View File

@@ -1,5 +1,5 @@
/* deepscan-disable USELESS_ARROW_FUNC_BIND */
import { Meta, Story } from '@storybook/react';
import { Meta, StoryFn } from '@storybook/react';
import { Button } from '..';
import { ButtonProps } from '../ui/button/interface';
@@ -13,7 +13,7 @@ export default {
},
} as Meta<ButtonProps>;
const Template: Story<ButtonProps> = args => <Button {...args} />;
const Template: StoryFn<ButtonProps> = args => <Button {...args} />;
export const Primary = Template.bind(undefined);
Primary.args = {