mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 05:14:54 +00:00
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. 
This commit is contained in:
41
packages/frontend/core/src/utils/island.tsx
Normal file
41
packages/frontend/core/src/utils/island.tsx
Normal 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>;
|
||||
Reference in New Issue
Block a user