feat(core): split right sidebar (#5971)

https://github.com/toeverything/AFFiNE/assets/13579374/c846c069-aa32-445d-b59b-b773a9b05ced

Now each view has a general container, the yellow area is the general container part, and the green part is the routing specific part.

![CleanShot 2024-03-01 at 11.47.35@2x.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/g3jz87HxbjOJpXV3FPT7/9a9f6ad6-2207-42e5-ae66-f7426bc9f3fc.png)
This commit is contained in:
EYHN
2024-03-04 06:42:12 +00:00
parent e2a31ea1fc
commit c599715963
88 changed files with 1393 additions and 1238 deletions

View File

@@ -0,0 +1,41 @@
import { LiveData, useLiveData } from '@toeverything/infra/livedata';
import { useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
export const createIsland = () => {
const targetLiveData = new LiveData<HTMLDivElement | null>(null);
let mounted = false;
let provided = false;
return {
Target: ({ ...other }: React.HTMLProps<HTMLDivElement>) => {
const target = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (mounted === true) {
throw new Error('Island should not be mounted more than once');
}
mounted = true;
targetLiveData.next(target.current);
return () => {
mounted = false;
targetLiveData.next(null);
};
}, []);
return <div {...other} ref={target}></div>;
},
Provider: ({ children }: React.PropsWithChildren) => {
const target = useLiveData(targetLiveData);
useEffect(() => {
if (provided === true && process.env.NODE_ENV !== 'production') {
throw new Error('Island should not be provided more than once');
}
provided = true;
return () => {
provided = false;
};
}, []);
return target ? createPortal(children, target) : null;
},
};
};
export type Island = ReturnType<typeof createIsland>;