mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-10 13:38:49 +08:00
Merge pull request #493 from toeverything/develop
Sync develop to master
This commit is contained in:
@@ -383,7 +383,7 @@ export const AFFiNEFooter = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography sx={{ display: 'flex', color: '#888' }}>
|
<Typography sx={{ display: 'flex', color: '#888' }}>
|
||||||
Copyright © 2022 AFFiNE.
|
Copyright © 2022 Toeverything
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
"Feedback": "反馈",
|
"Feedback": "反馈",
|
||||||
"ContactUs": "联系我们",
|
"ContactUs": "联系我们",
|
||||||
"Alternative": "的另一种选择",
|
"Alternative": "的另一种选择",
|
||||||
"Check GitHub": "GitHub中查看",
|
"Check GitHub": "GitHub 中查看",
|
||||||
"Try it Online": "在线试用",
|
"Try it Online": "在线试用",
|
||||||
"language": "语言",
|
"language": "语言",
|
||||||
"description1": {
|
"description1": {
|
||||||
"part1": "Affine是面向专业人士的下一代协同知识库",
|
"part1": "Affine 是面向专业人士的下一代协同知识库",
|
||||||
"part2": "它不仅仅是一个文档、白板和表格的集合。",
|
"part2": "它不仅仅是一个文档、白板和表格的集合。",
|
||||||
"part3": "可以根据需要转换任何构建块。",
|
"part3": "可以根据需要转换任何构建块。",
|
||||||
"part4": "向冗余说再见吧。将数据存储一次,并保留您喜欢的数据。"
|
"part4": "向冗余说再见吧。将数据存储一次,并保留您喜欢的数据。"
|
||||||
|
|||||||
@@ -7,29 +7,28 @@ We're open for Fullstack Engineer positions across the BlockSuite sub-team. The
|
|||||||
|
|
||||||
### This position is for:
|
### This position is for:
|
||||||
|
|
||||||
- Develop AFFiNE **the open source way**, including coding and community engagement.
|
- Developing AFFiNE **the open source way**, including coding and community engagement.
|
||||||
- Researching and supporting onboarding of new use cases AFFiNE.pro subscribers.
|
- Researching and supporting onboarding of new use cases AFFiNE.pro subscribers.
|
||||||
- Improving our **block editor** and **graphic editor**.
|
- Improving our **block editor** and **graphics editor**.
|
||||||
- Assist our subscribers in utilizing our product in a data-based way with help from the operational teams.
|
- Assisting our subscribers in utilizing our product in a data-based way with help from the operational teams.
|
||||||
- Research on better activation of potential subscribers. At AFFiNE, developers are self-organized individual engineers who are also responsible team members whether they are on-site or working remotely.
|
- Researching on better activation of potential subscribers. At AFFiNE, developers are self-organized individual engineers who are also responsible team members whether they are on-site or working remotely.
|
||||||
|
|
||||||
### What we are looking for:
|
### What we are looking for:
|
||||||
|
|
||||||
- Software engineering experience with **editor** or **graphics** with professional real-world use cases.
|
- Software engineering experience with **editor** or **graphics** with professional real-world use cases.
|
||||||
- Experience and proficiency in **JavaScript** and a **second programming language** preferably **Rust**.
|
- Experience and proficiency in **TypeScript** and a **second programming language** preferably **Rust**.
|
||||||
- You have strong communication and writing skills in English.
|
- You have strong communication and writing skills in English.
|
||||||
- You are comfortable working in a diverse and cross-functional team.
|
- You are comfortable working in a diverse and cross-functional team.
|
||||||
- You love the spirit of open source, share our visions and work under those values.
|
- You love the spirit of open source, share our visions and work under those values.
|
||||||
|
|
||||||
### It would be great if you have/are:
|
### It would be great if you are:
|
||||||
|
|
||||||
- Incredible **React** or **web components (lit)** experts.
|
- Skillful in building UI with different Web frameworks or native web components.
|
||||||
- Knowledge/project management tool enthusiast.
|
- Heavy user of knowledge/project management tools.
|
||||||
- Licensing or subscription management or enterprise software company experience.
|
- Experienced in scaling **a successful SaaS product**.
|
||||||
- Experience scaling **a successful SaaS product**.
|
- Experienced in developing platforms or tools for developers.
|
||||||
- Developer platform/tool industry experience.
|
- Experienced in working with a **globally distributed team**.
|
||||||
- Experience working with a **globally distributed team**.
|
- Enthusiastic in AFFiNE products as a user or contributor.
|
||||||
- Love AFFiNE products as a user or contributor.
|
|
||||||
|
|
||||||
### What we offer:
|
### What we offer:
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ export const useShapes = (workspace: string, rootBlockId: string) => {
|
|||||||
parentId: rootBlockId,
|
parentId: rootBlockId,
|
||||||
...shapeProps,
|
...shapeProps,
|
||||||
id: block.id,
|
id: block.id,
|
||||||
style: { ...defaultStyle },
|
style: { ...defaultStyle, ...(shapeProps.style || {}) },
|
||||||
workspace,
|
workspace,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1138,6 +1138,15 @@ class SlateUtils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public removeBetweenPoints(startPoint: Point, endPoint: Point) {
|
||||||
|
const at = {
|
||||||
|
anchor: startPoint,
|
||||||
|
focus: endPoint,
|
||||||
|
};
|
||||||
|
Transforms.select(this.editor, at);
|
||||||
|
this.editor.deleteFragment();
|
||||||
|
}
|
||||||
|
|
||||||
public setDoubleLinkSearchSlash(point: Point) {
|
public setDoubleLinkSearchSlash(point: Point) {
|
||||||
const str = Editor.string(this.editor, {
|
const str = Editor.string(this.editor, {
|
||||||
anchor: this.getStart(),
|
anchor: this.getStart(),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
} from 'slate';
|
} from 'slate';
|
||||||
import { AsyncBlock } from '../block';
|
import { AsyncBlock } from '../block';
|
||||||
import { Editor } from '../editor';
|
import { Editor } from '../editor';
|
||||||
import { SelectBlock } from '../selection';
|
import { SelectBlock, type SelectInfo } from '../selection';
|
||||||
|
|
||||||
type TextUtilsFunctions =
|
type TextUtilsFunctions =
|
||||||
| 'getString'
|
| 'getString'
|
||||||
@@ -40,6 +40,7 @@ type TextUtilsFunctions =
|
|||||||
| 'getCommentsIdsBySelection'
|
| 'getCommentsIdsBySelection'
|
||||||
| 'getCurrentSelection'
|
| 'getCurrentSelection'
|
||||||
| 'removeSelection'
|
| 'removeSelection'
|
||||||
|
| 'removeBetweenPoints'
|
||||||
| 'isCollapsed'
|
| 'isCollapsed'
|
||||||
| 'blur'
|
| 'blur'
|
||||||
| 'setSelection'
|
| 'setSelection'
|
||||||
@@ -528,4 +529,32 @@ export class BlockHelper {
|
|||||||
console.warn('Could find the block text utils');
|
console.warn('Could find the block text utils');
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public removeSelection(selection: SelectInfo) {
|
||||||
|
if (selection.type === 'Range') {
|
||||||
|
selection.blocks.forEach(async selectBlockInfo => {
|
||||||
|
const text_utils =
|
||||||
|
this._blockTextUtilsMap[selectBlockInfo.blockId];
|
||||||
|
text_utils.removeBetweenPoints(
|
||||||
|
{
|
||||||
|
path: [0, selectBlockInfo.startInfo.arrayIndex],
|
||||||
|
offset: selectBlockInfo.startInfo.offset,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: [0, selectBlockInfo.endInfo.arrayIndex],
|
||||||
|
offset: selectBlockInfo.endInfo.offset,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else if (selection.type === 'Block') {
|
||||||
|
selection.blocks.forEach(async selectBlockInfo => {
|
||||||
|
(
|
||||||
|
await this._editor.getBlock({
|
||||||
|
workspace: this._editor.workspace,
|
||||||
|
id: selectBlockInfo.blockId,
|
||||||
|
})
|
||||||
|
).remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { ClipboardEventDispatcher } from './clipboardEventDispatcher';
|
|
||||||
import { HookType } from '../types';
|
|
||||||
import { Editor } from '../editor';
|
import { Editor } from '../editor';
|
||||||
|
import { HookType } from '../types';
|
||||||
|
import { ClipboardEventDispatcher } from './clipboardEventDispatcher';
|
||||||
import { Copy } from './copy';
|
import { Copy } from './copy';
|
||||||
|
import { Cut } from './cut';
|
||||||
import { Paste } from './paste';
|
import { Paste } from './paste';
|
||||||
|
|
||||||
import { ClipboardUtils } from './clipboardUtils';
|
import { ClipboardUtils } from './clipboardUtils';
|
||||||
@@ -9,6 +10,7 @@ import { ClipboardUtils } from './clipboardUtils';
|
|||||||
export class Clipboard {
|
export class Clipboard {
|
||||||
private _clipboardEventDispatcher: ClipboardEventDispatcher;
|
private _clipboardEventDispatcher: ClipboardEventDispatcher;
|
||||||
private _copy: Copy;
|
private _copy: Copy;
|
||||||
|
private _cut: Cut;
|
||||||
private _paste: Paste;
|
private _paste: Paste;
|
||||||
public clipboardUtils: ClipboardUtils;
|
public clipboardUtils: ClipboardUtils;
|
||||||
private _clipboardTarget: HTMLElement;
|
private _clipboardTarget: HTMLElement;
|
||||||
@@ -17,7 +19,7 @@ export class Clipboard {
|
|||||||
this.clipboardUtils = new ClipboardUtils(editor);
|
this.clipboardUtils = new ClipboardUtils(editor);
|
||||||
this._clipboardTarget = clipboardTarget;
|
this._clipboardTarget = clipboardTarget;
|
||||||
this._copy = new Copy(editor);
|
this._copy = new Copy(editor);
|
||||||
|
this._cut = new Cut(editor);
|
||||||
this._paste = new Paste(editor);
|
this._paste = new Paste(editor);
|
||||||
|
|
||||||
this._clipboardEventDispatcher = new ClipboardEventDispatcher(
|
this._clipboardEventDispatcher = new ClipboardEventDispatcher(
|
||||||
@@ -30,7 +32,7 @@ export class Clipboard {
|
|||||||
.get(HookType.ON_COPY)
|
.get(HookType.ON_COPY)
|
||||||
.subscribe(this._copy.handleCopy);
|
.subscribe(this._copy.handleCopy);
|
||||||
|
|
||||||
editor.getHooks().get(HookType.ON_CUT).subscribe(this._copy.handleCopy);
|
editor.getHooks().get(HookType.ON_CUT).subscribe(this._cut.handleCut);
|
||||||
|
|
||||||
editor
|
editor
|
||||||
.getHooks()
|
.getHooks()
|
||||||
|
|||||||
@@ -0,0 +1,183 @@
|
|||||||
|
import { Editor } from '../editor';
|
||||||
|
import { SelectInfo } from '../selection';
|
||||||
|
import { Clip } from './clip';
|
||||||
|
import { ClipboardUtils } from './clipboardUtils';
|
||||||
|
import { OFFICE_CLIPBOARD_MIMETYPE } from './types';
|
||||||
|
class Cut {
|
||||||
|
private _editor: Editor;
|
||||||
|
private _utils: ClipboardUtils;
|
||||||
|
constructor(editor: Editor) {
|
||||||
|
this._editor = editor;
|
||||||
|
this._utils = new ClipboardUtils(editor);
|
||||||
|
this.handleCut = this.handleCut.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async handleCut(e: ClipboardEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
const selectInfo: SelectInfo =
|
||||||
|
await this._editor.selectionManager.getSelectInfo();
|
||||||
|
|
||||||
|
const clips = await this.getClips(selectInfo);
|
||||||
|
if (!clips.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const success = this._copyToClipboardFromPc(clips);
|
||||||
|
if (!success) {
|
||||||
|
// This way, not compatible with firefox
|
||||||
|
const clipboardData = e.clipboardData;
|
||||||
|
if (clipboardData) {
|
||||||
|
try {
|
||||||
|
clips.forEach(clip => {
|
||||||
|
clipboardData.setData(
|
||||||
|
clip.getMimeType(),
|
||||||
|
clip.getData()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
// TODO handle exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._editor.blockHelper.removeSelection(selectInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getClips(selectInfo: SelectInfo) {
|
||||||
|
const clips: Clip[] = [];
|
||||||
|
|
||||||
|
// get custom clip
|
||||||
|
const affineClip = await this._getAffineClip(selectInfo);
|
||||||
|
clips.push(affineClip);
|
||||||
|
|
||||||
|
const textClip = await this._getTextClip(selectInfo);
|
||||||
|
clips.push(textClip);
|
||||||
|
|
||||||
|
const htmlClip = await this._getHtmlClip(selectInfo);
|
||||||
|
|
||||||
|
clips.push(htmlClip);
|
||||||
|
|
||||||
|
return clips;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _getHtmlClip(selectInfo: SelectInfo): Promise<Clip> {
|
||||||
|
const htmlStr = (
|
||||||
|
await Promise.all(
|
||||||
|
selectInfo.blocks.map(async selectBlockInfo => {
|
||||||
|
const block = await this._editor.getBlockById(
|
||||||
|
selectBlockInfo.blockId
|
||||||
|
);
|
||||||
|
const blockView = this._editor.getView(block.type);
|
||||||
|
return await blockView.block2html({
|
||||||
|
editor: this._editor,
|
||||||
|
block,
|
||||||
|
selectInfo: selectBlockInfo,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
)
|
||||||
|
).join('');
|
||||||
|
|
||||||
|
return new Clip(OFFICE_CLIPBOARD_MIMETYPE.HTML, htmlStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _getAffineClip(selectInfo: SelectInfo): Promise<Clip> {
|
||||||
|
if (selectInfo.type === 'Range') {
|
||||||
|
return this._utils.getClipDataOfBlocksBySelectInfo(selectInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The only remaining case is that selectInfo.type === 'Block'
|
||||||
|
return this._utils.getClipDataOfBlocksById(
|
||||||
|
selectInfo.blocks.map(block => block.blockId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _getTextClip(selectInfo: SelectInfo): Promise<Clip> {
|
||||||
|
if (selectInfo.type === 'Range') {
|
||||||
|
const text = (
|
||||||
|
await Promise.all(
|
||||||
|
selectInfo.blocks.map(async selectBlockInfo => {
|
||||||
|
const block = await this._editor.getBlockById(
|
||||||
|
selectBlockInfo.blockId
|
||||||
|
);
|
||||||
|
const blockView = this._editor.getView(block.type);
|
||||||
|
const block2Text = await blockView.block2Text(
|
||||||
|
block,
|
||||||
|
selectBlockInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
block2Text ||
|
||||||
|
this._editor.blockHelper.getBlockTextBetweenSelection(
|
||||||
|
selectBlockInfo.blockId,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
).join('\n');
|
||||||
|
return new Clip(OFFICE_CLIPBOARD_MIMETYPE.TEXT, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The only remaining case is that selectInfo.type === 'Block'
|
||||||
|
const selectedBlocks = (
|
||||||
|
await Promise.all(
|
||||||
|
selectInfo.blocks.map(selectBlockInfo =>
|
||||||
|
this._editor.blockHelper.getFlatBlocksUnderParent(
|
||||||
|
selectBlockInfo.blockId,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).flat();
|
||||||
|
|
||||||
|
const blockText = (
|
||||||
|
await Promise.all(
|
||||||
|
selectedBlocks.map(async block => {
|
||||||
|
const blockView = this._editor.getView(block.type);
|
||||||
|
const block2Text = await blockView.block2Text(block);
|
||||||
|
return (
|
||||||
|
block2Text ||
|
||||||
|
this._editor.blockHelper.getBlockText(block.id)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
).join('\n');
|
||||||
|
|
||||||
|
return new Clip(OFFICE_CLIPBOARD_MIMETYPE.TEXT, blockText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Optimization
|
||||||
|
// TODO: is not compatible with safari
|
||||||
|
private _copyToClipboardFromPc(clips: any[]) {
|
||||||
|
let success = false;
|
||||||
|
const tempElem = document.createElement('textarea');
|
||||||
|
tempElem.value = 'temp';
|
||||||
|
document.body.appendChild(tempElem);
|
||||||
|
tempElem.select();
|
||||||
|
tempElem.setSelectionRange(0, tempElem.value.length);
|
||||||
|
|
||||||
|
const listener = function (e: any) {
|
||||||
|
const clipboardData = e.clipboardData;
|
||||||
|
if (clipboardData) {
|
||||||
|
clips.forEach(clip => {
|
||||||
|
clipboardData.setData(clip.getMimeType(), clip.getData());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
tempElem.removeEventListener('copy', listener);
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
tempElem.addEventListener('copy', listener);
|
||||||
|
try {
|
||||||
|
success = document.execCommand('copy');
|
||||||
|
} finally {
|
||||||
|
tempElem.removeEventListener('copy', listener);
|
||||||
|
document.body.removeChild(tempElem);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Cut };
|
||||||
@@ -54,7 +54,7 @@ export class Editor implements Virgo {
|
|||||||
public bdCommands: Commands;
|
public bdCommands: Commands;
|
||||||
public ui_container?: HTMLDivElement;
|
public ui_container?: HTMLDivElement;
|
||||||
public version = '0.0.1';
|
public version = '0.0.1';
|
||||||
public copyright = '@AFFiNE 2020-2022';
|
public copyright = '@Toeverything 2022';
|
||||||
private plugin_manager: PluginManager;
|
private plugin_manager: PluginManager;
|
||||||
private hooks: Hooks;
|
private hooks: Hooks;
|
||||||
private views: Record<string, BaseView> = {};
|
private views: Record<string, BaseView> = {};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
useLocalTrigger,
|
useLocalTrigger,
|
||||||
useShowSettingsSidebar,
|
useShowSettingsSidebar,
|
||||||
} from '@toeverything/datasource/state';
|
} from '@toeverything/datasource/state';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { EditorBoardSwitcher } from './EditorBoardSwitcher';
|
import { EditorBoardSwitcher } from './EditorBoardSwitcher';
|
||||||
import { fsApiSupported } from './FileSystem';
|
import { fsApiSupported } from './FileSystem';
|
||||||
import { Logo } from './Logo';
|
import { Logo } from './Logo';
|
||||||
@@ -23,6 +23,23 @@ export const LayoutHeader = () => {
|
|||||||
useShowSettingsSidebar();
|
useShowSettingsSidebar();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
// because of header not compatible with small screen, hide the mode switcher in that case, this will be optimize in future.
|
||||||
|
const [hideSwitcher, setHideSwither] = useState(false);
|
||||||
|
const [rootEle, setRootEle] = useState<HTMLDivElement>();
|
||||||
|
useEffect(() => {
|
||||||
|
if (rootEle) {
|
||||||
|
const observer = new ResizeObserver(entries => {
|
||||||
|
setHideSwither(entries[0].contentRect.width < 970);
|
||||||
|
});
|
||||||
|
observer.observe(rootEle);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.disconnect();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, [rootEle]);
|
||||||
|
|
||||||
const warningTips = useMemo(() => {
|
const warningTips = useMemo(() => {
|
||||||
if (!fsApiSupported()) {
|
if (!fsApiSupported()) {
|
||||||
return t('WarningTips.IsNotfsApiSupported');
|
return t('WarningTips.IsNotfsApiSupported');
|
||||||
@@ -42,7 +59,7 @@ export const LayoutHeader = () => {
|
|||||||
}, [currentEditors]);
|
}, [currentEditors]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainerForHeaderRoot>
|
<StyledContainerForHeaderRoot ref={setRootEle}>
|
||||||
<StyledHeaderRoot>
|
<StyledHeaderRoot>
|
||||||
<FlexContainer>
|
<FlexContainer>
|
||||||
<Logo />
|
<Logo />
|
||||||
@@ -85,9 +102,11 @@ export const LayoutHeader = () => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</StyledHelper>
|
</StyledHelper>
|
||||||
</FlexContainer>
|
</FlexContainer>
|
||||||
<StyledContainerForEditorBoardSwitcher>
|
{hideSwitcher ? null : (
|
||||||
<EditorBoardSwitcher />
|
<StyledContainerForEditorBoardSwitcher>
|
||||||
</StyledContainerForEditorBoardSwitcher>
|
<EditorBoardSwitcher />
|
||||||
|
</StyledContainerForEditorBoardSwitcher>
|
||||||
|
)}
|
||||||
</StyledHeaderRoot>
|
</StyledHeaderRoot>
|
||||||
</StyledContainerForHeaderRoot>
|
</StyledContainerForHeaderRoot>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const InfoModal = ({ open, onClose }: ModalProps) => {
|
|||||||
</CloseContainer>
|
</CloseContainer>
|
||||||
</Header>
|
</Header>
|
||||||
<ModalContent />
|
<ModalContent />
|
||||||
<Footer>Copyright © 2022 AFFINE</Footer>
|
<Footer>Copyright © 2022 Toeverything</Footer>
|
||||||
</Container>
|
</Container>
|
||||||
</MuiModal>
|
</MuiModal>
|
||||||
);
|
);
|
||||||
@@ -35,7 +35,7 @@ const Container = styled('div')({
|
|||||||
transform: 'translate(-50%, -50%)',
|
transform: 'translate(-50%, -50%)',
|
||||||
width: '60%',
|
width: '60%',
|
||||||
maxWidth: '1000px',
|
maxWidth: '1000px',
|
||||||
minWidth: '840px',
|
minWidth: '860px',
|
||||||
borderRadius: '28px',
|
borderRadius: '28px',
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
padding: '48px 48px 40px 48px',
|
padding: '48px 48px 40px 48px',
|
||||||
|
|||||||
@@ -32,11 +32,13 @@ export const TransitionsModal = (props: TransitionsModalProps) => {
|
|||||||
onClose={props.onClose}
|
onClose={props.onClose}
|
||||||
closeAfterTransition
|
closeAfterTransition
|
||||||
>
|
>
|
||||||
<MuiClickAwayListener onClickAway={props.onClose}>
|
<div>
|
||||||
<Fade in={props.open} timeout={300}>
|
<MuiClickAwayListener onClickAway={props.onClose}>
|
||||||
{props.children}
|
<Fade in={props.open} timeout={300}>
|
||||||
</Fade>
|
{props.children}
|
||||||
</MuiClickAwayListener>
|
</Fade>
|
||||||
|
</MuiClickAwayListener>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,8 +25,11 @@ export const placementToContainerDirection: Record<
|
|||||||
'auto-end': 'none',
|
'auto-end': 'none',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Popover = (props: PropsWithChildren<PopoverProps>) => {
|
export const Popover = ({
|
||||||
const { popoverDirection, placement, content, children, style } = props;
|
popoverDirection,
|
||||||
|
...props
|
||||||
|
}: PropsWithChildren<PopoverProps>) => {
|
||||||
|
const { placement, content, children, style } = props;
|
||||||
return (
|
return (
|
||||||
<Popper
|
<Popper
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
Reference in New Issue
Block a user