mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-17 01:56:27 +08:00
Merge remote-tracking branch 'origin/develop' into fix/experience
This commit is contained in:
@@ -1,29 +1,28 @@
|
||||
import type { TextProps } from '@toeverything/components/common';
|
||||
import {
|
||||
ContentColumnValue,
|
||||
services,
|
||||
Protocol,
|
||||
services,
|
||||
} from '@toeverything/datasource/db-service';
|
||||
import { type CreateView } from '@toeverything/framework/virgo';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import {
|
||||
BlockPendantProvider,
|
||||
RenderBlockChildren,
|
||||
supportChildren,
|
||||
useOnSelect,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
import { BlockContainer } from '../../components/BlockContainer';
|
||||
import { List } from '../../components/style-container';
|
||||
import {
|
||||
TextManage,
|
||||
type ExtendedTextUtils,
|
||||
} from '../../components/text-manage';
|
||||
import { tabBlock } from '../../utils/indent';
|
||||
import { BulletIcon, getChildrenType, NumberType } from './data';
|
||||
import { BulletBlock, BulletProperties } from './types';
|
||||
import {
|
||||
supportChildren,
|
||||
RenderBlockChildren,
|
||||
useOnSelect,
|
||||
BlockPendantProvider,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { List } from '../../components/style-container';
|
||||
import { getChildrenType, BulletIcon, NumberType } from './data';
|
||||
import { IndentWrapper } from '../../components/IndentWrapper';
|
||||
import { BlockContainer } from '../../components/BlockContainer';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
|
||||
export const defaultBulletProps: BulletProperties = {
|
||||
text: { value: [{ text: '' }] },
|
||||
@@ -208,9 +207,7 @@ export const BulletView = ({ block, editor }: CreateView) => {
|
||||
</div>
|
||||
</List>
|
||||
</BlockPendantProvider>
|
||||
<IndentWrapper>
|
||||
<RenderBlockChildren block={block} />
|
||||
</IndentWrapper>
|
||||
<RenderBlockChildren block={block} />
|
||||
</BlockContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import {
|
||||
AsyncBlock,
|
||||
BaseView,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { defaultBulletProps, BulletView } from './BulletView';
|
||||
|
||||
import {
|
||||
Block2HtmlProps,
|
||||
commonBlock2HtmlContent,
|
||||
commonHTML2block,
|
||||
} from '../../utils/commonBlockClip';
|
||||
import { BulletView, defaultBulletProps } from './BulletView';
|
||||
|
||||
export class BulletBlock extends BaseView {
|
||||
public type = Protocol.Block.Type.bullet;
|
||||
|
||||
|
||||
@@ -1,58 +1,54 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { StyleWithAtRules } from 'style9';
|
||||
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import CodeMirror, { ReactCodeMirrorRef } from './CodeMirror';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import { css } from '@codemirror/lang-css';
|
||||
import { json } from '@codemirror/lang-json';
|
||||
import { python } from '@codemirror/lang-python';
|
||||
import { markdown } from '@codemirror/lang-markdown';
|
||||
import { xml } from '@codemirror/lang-xml';
|
||||
import { sql, MySQL, PostgreSQL } from '@codemirror/lang-sql';
|
||||
import { java } from '@codemirror/lang-java';
|
||||
import { rust } from '@codemirror/lang-rust';
|
||||
import { cpp } from '@codemirror/lang-cpp';
|
||||
import { css } from '@codemirror/lang-css';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import { java } from '@codemirror/lang-java';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { json } from '@codemirror/lang-json';
|
||||
import { lezer } from '@codemirror/lang-lezer';
|
||||
import { markdown } from '@codemirror/lang-markdown';
|
||||
import { php } from '@codemirror/lang-php';
|
||||
import { python } from '@codemirror/lang-python';
|
||||
import { rust } from '@codemirror/lang-rust';
|
||||
import { MySQL, PostgreSQL, sql } from '@codemirror/lang-sql';
|
||||
import { xml } from '@codemirror/lang-xml';
|
||||
import { StreamLanguage } from '@codemirror/language';
|
||||
import { go } from '@codemirror/legacy-modes/mode/go';
|
||||
import { ruby } from '@codemirror/legacy-modes/mode/ruby';
|
||||
import { shell } from '@codemirror/legacy-modes/mode/shell';
|
||||
import { lua } from '@codemirror/legacy-modes/mode/lua';
|
||||
import { swift } from '@codemirror/legacy-modes/mode/swift';
|
||||
import { tcl } from '@codemirror/legacy-modes/mode/tcl';
|
||||
import { yaml } from '@codemirror/legacy-modes/mode/yaml';
|
||||
import { vb } from '@codemirror/legacy-modes/mode/vb';
|
||||
import { powerShell } from '@codemirror/legacy-modes/mode/powershell';
|
||||
import { brainfuck } from '@codemirror/legacy-modes/mode/brainfuck';
|
||||
import { stylus } from '@codemirror/legacy-modes/mode/stylus';
|
||||
import { erlang } from '@codemirror/legacy-modes/mode/erlang';
|
||||
import { elixir } from 'codemirror-lang-elixir';
|
||||
import { nginx } from '@codemirror/legacy-modes/mode/nginx';
|
||||
import { perl } from '@codemirror/legacy-modes/mode/perl';
|
||||
import { pascal } from '@codemirror/legacy-modes/mode/pascal';
|
||||
import { liveScript } from '@codemirror/legacy-modes/mode/livescript';
|
||||
import { scheme } from '@codemirror/legacy-modes/mode/scheme';
|
||||
import { toml } from '@codemirror/legacy-modes/mode/toml';
|
||||
import { vbScript } from '@codemirror/legacy-modes/mode/vbscript';
|
||||
import { clojure } from '@codemirror/legacy-modes/mode/clojure';
|
||||
import { coffeeScript } from '@codemirror/legacy-modes/mode/coffeescript';
|
||||
import { dockerFile } from '@codemirror/legacy-modes/mode/dockerfile';
|
||||
import { erlang } from '@codemirror/legacy-modes/mode/erlang';
|
||||
import { go } from '@codemirror/legacy-modes/mode/go';
|
||||
import { julia } from '@codemirror/legacy-modes/mode/julia';
|
||||
import { liveScript } from '@codemirror/legacy-modes/mode/livescript';
|
||||
import { lua } from '@codemirror/legacy-modes/mode/lua';
|
||||
import { nginx } from '@codemirror/legacy-modes/mode/nginx';
|
||||
import { pascal } from '@codemirror/legacy-modes/mode/pascal';
|
||||
import { perl } from '@codemirror/legacy-modes/mode/perl';
|
||||
import { powerShell } from '@codemirror/legacy-modes/mode/powershell';
|
||||
import { r } from '@codemirror/legacy-modes/mode/r';
|
||||
import { ruby } from '@codemirror/legacy-modes/mode/ruby';
|
||||
import { scheme } from '@codemirror/legacy-modes/mode/scheme';
|
||||
import { shell } from '@codemirror/legacy-modes/mode/shell';
|
||||
import { stylus } from '@codemirror/legacy-modes/mode/stylus';
|
||||
import { swift } from '@codemirror/legacy-modes/mode/swift';
|
||||
import { tcl } from '@codemirror/legacy-modes/mode/tcl';
|
||||
import { toml } from '@codemirror/legacy-modes/mode/toml';
|
||||
import { vb } from '@codemirror/legacy-modes/mode/vb';
|
||||
import { vbScript } from '@codemirror/legacy-modes/mode/vbscript';
|
||||
import { yaml } from '@codemirror/legacy-modes/mode/yaml';
|
||||
import { Extension } from '@codemirror/state';
|
||||
import { Option, Select } from '@toeverything/components/ui';
|
||||
|
||||
import {
|
||||
useOnSelect,
|
||||
BlockPendantProvider,
|
||||
useOnSelect,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { copyToClipboard } from '@toeverything/utils';
|
||||
import { DuplicateIcon } from '@toeverything/components/icons';
|
||||
import { Option, Select, styled } from '@toeverything/components/ui';
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import { copyToClipboard } from '@toeverything/utils';
|
||||
import { elixir } from 'codemirror-lang-elixir';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { StyleWithAtRules } from 'style9';
|
||||
import CodeMirror, { ReactCodeMirrorRef } from './CodeMirror';
|
||||
|
||||
interface CreateCodeView extends CreateView {
|
||||
style9?: StyleWithAtRules;
|
||||
@@ -110,13 +106,15 @@ const CodeBlock = styled('div')(({ theme }) => ({
|
||||
borderRadius: theme.affine.shape.borderRadius,
|
||||
'&:hover': {
|
||||
'.operation': {
|
||||
display: 'flex',
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
'.operation': {
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'space-between',
|
||||
opacity: 0,
|
||||
transition: 'opacity 1.5s',
|
||||
},
|
||||
'.copy-block': {
|
||||
padding: '0px 10px',
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
export class CodeBlock extends BaseView {
|
||||
type = Protocol.Block.Type.code;
|
||||
public override selectable = true;
|
||||
public override activatable = false;
|
||||
public override editable = false;
|
||||
// View = CodeView;
|
||||
View = CodeView;
|
||||
override async onCreate(block: AsyncBlock): Promise<AsyncBlock> {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useState } from 'react';
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import {
|
||||
BlockPendantProvider,
|
||||
useOnSelect,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { Upload } from '../../components/upload/upload';
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import { useState } from 'react';
|
||||
import { SourceView } from '../../components/source-view';
|
||||
import { LinkContainer } from '../../components/style-container';
|
||||
import { Upload } from '../../components/upload/upload';
|
||||
|
||||
const MESSAGES = {
|
||||
ADD_EMBED_LINK: 'Add embed link',
|
||||
@@ -38,7 +38,6 @@ export const EmbedLinkView = (props: EmbedLinkView) => {
|
||||
{embedLinkUrl ? (
|
||||
<SourceView
|
||||
block={block}
|
||||
editorElement={props.editorElement}
|
||||
isSelected={isSelect}
|
||||
viewType="embedLink"
|
||||
link={embedLinkUrl}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Block2HtmlProps } from '../../utils/commonBlockClip';
|
||||
|
||||
export class EmbedLinkBlock extends BaseView {
|
||||
public override selectable = true;
|
||||
public override activatable = false;
|
||||
public override editable = false;
|
||||
type = Protocol.Block.Type.embedLink;
|
||||
View = EmbedLinkView;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Block2HtmlProps } from '../../utils/commonBlockClip';
|
||||
|
||||
export class FigmaBlock extends BaseView {
|
||||
public override selectable = true;
|
||||
public override activatable = false;
|
||||
public override editable = false;
|
||||
type = Protocol.Block.Type.figma;
|
||||
View = FigmaView;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Block2HtmlProps } from '../../utils/commonBlockClip';
|
||||
|
||||
export class FileBlock extends BaseView {
|
||||
public override selectable = true;
|
||||
public override activatable = false;
|
||||
public override editable = false;
|
||||
type = Protocol.Block.Type.file;
|
||||
View = FileView;
|
||||
override async block2html({ block }: Block2HtmlProps) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RenderBlock } from '@toeverything/components/editor-core';
|
||||
import { useBlockRender } from '@toeverything/components/editor-core';
|
||||
import { ChildrenView, CreateView } from '@toeverything/framework/virgo';
|
||||
|
||||
export const GridItemRender = function (
|
||||
@@ -6,10 +6,11 @@ export const GridItemRender = function (
|
||||
) {
|
||||
const GridItem = function (props: CreateView) {
|
||||
const { block } = props;
|
||||
const { BlockRender } = useBlockRender();
|
||||
const children = (
|
||||
<>
|
||||
{block.childrenIds.map(id => {
|
||||
return <RenderBlock key={id} blockId={id} />;
|
||||
return <BlockRender key={id} blockId={id} />;
|
||||
})}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { GridItemRender } from './GridItemRender';
|
||||
|
||||
export class GridItemBlock extends BaseView {
|
||||
public override selectable = false;
|
||||
public override activatable = false;
|
||||
public override editable = false;
|
||||
public override allowPendant = false;
|
||||
public override layoutOnly = true;
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { RenderBlock } from '@toeverything/components/editor-core';
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { GridHandle } from './GirdHandle';
|
||||
import { useBlockRender } from '@toeverything/components/editor-core';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import { debounce, domToRect, Point } from '@toeverything/utils';
|
||||
import clsx from 'clsx';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {
|
||||
GRID_ITEM_CLASS_NAME,
|
||||
GRID_ITEM_CONTENT_CLASS_NAME,
|
||||
} from '../grid-item/GridItem';
|
||||
import { debounce, domToRect, Point } from '@toeverything/utils';
|
||||
import clsx from 'clsx';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { GridHandle } from './GirdHandle';
|
||||
|
||||
const DB_UPDATE_DELAY = 50;
|
||||
const GRID_ON_DRAG_CLASS = 'grid-layout-on-drag';
|
||||
@@ -31,6 +31,7 @@ export const Grid = function (props: CreateView) {
|
||||
const originalLeftWidth = useRef<number>(gridItemMinWidth);
|
||||
const originalRightWidth = useRef<number>(gridItemMinWidth);
|
||||
const [alertHandleId, setAlertHandleId] = useState<string>(null);
|
||||
const { BlockRender } = useBlockRender();
|
||||
|
||||
const getLeftRightGridItemDomByIndex = (index: number) => {
|
||||
const gridItems = Array.from(gridContainerRef.current?.children).filter(
|
||||
@@ -226,7 +227,7 @@ export const Grid = function (props: CreateView) {
|
||||
key={id}
|
||||
className={GRID_ITEM_CLASS_NAME}
|
||||
>
|
||||
<RenderBlock hasContainer={false} blockId={id} />
|
||||
<BlockRender hasContainer={false} blockId={id} />
|
||||
<GridHandle
|
||||
onDrag={event => handleDragGrid(event, i)}
|
||||
editor={editor}
|
||||
|
||||
@@ -7,7 +7,7 @@ export { GRID_PROPERTY_KEY, removePercent } from './Grid';
|
||||
|
||||
export class GridBlock extends BaseView {
|
||||
public override selectable = false;
|
||||
public override activatable = false;
|
||||
public override editable = false;
|
||||
public override allowPendant = false;
|
||||
public override layoutOnly = true;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
|
||||
export class Group extends BaseView {
|
||||
public override selectable = true;
|
||||
public override activatable = false;
|
||||
public override editable = false;
|
||||
public override allowPendant = false;
|
||||
|
||||
type = Protocol.Block.Type.group;
|
||||
|
||||
@@ -2,5 +2,5 @@ import { RenderBlockChildren } from '@toeverything/components/editor-core';
|
||||
import type { CreateView } from '@toeverything/framework/virgo';
|
||||
|
||||
export const ScenePage = ({ block }: CreateView) => {
|
||||
return <RenderBlockChildren block={block} />;
|
||||
return <RenderBlockChildren block={block} indent={false} />;
|
||||
};
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import type { KanbanCard } from '@toeverything/components/editor-core';
|
||||
import {
|
||||
RenderBlock,
|
||||
KanbanCard,
|
||||
useBlockRender,
|
||||
useEditor,
|
||||
useKanban,
|
||||
useRefPage,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
import { PenIcon } from '@toeverything/components/icons';
|
||||
import {
|
||||
IconButton,
|
||||
MuiClickAwayListener,
|
||||
styled,
|
||||
} from '@toeverything/components/ui';
|
||||
import { useFlag } from '@toeverything/datasource/feature-flags';
|
||||
import { useState, type MouseEvent } from 'react';
|
||||
import { useRefPage } from './RefPage';
|
||||
|
||||
const CardContent = styled('div')({
|
||||
margin: '20px',
|
||||
@@ -23,6 +30,7 @@ const CardActions = styled('div')({
|
||||
fontWeight: '300',
|
||||
color: '#98ACBD',
|
||||
transition: 'all ease-in 0.2s',
|
||||
zIndex: 1,
|
||||
|
||||
':hover': {
|
||||
background: '#F5F7F8',
|
||||
@@ -39,11 +47,13 @@ const PlusIcon = styled('div')({
|
||||
});
|
||||
|
||||
const CardContainer = styled('div')({
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: '#fff',
|
||||
border: '1px solid #E2E7ED',
|
||||
borderRadius: '5px',
|
||||
overflow: 'hidden',
|
||||
|
||||
[CardActions.toString()]: {
|
||||
opacity: '0',
|
||||
@@ -55,6 +65,23 @@ const CardContainer = styled('div')({
|
||||
},
|
||||
});
|
||||
|
||||
const Overlay = styled('div')({
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
background: 'transparent',
|
||||
|
||||
'& > *': {
|
||||
visibility: 'hidden',
|
||||
position: 'absolute',
|
||||
right: '24px',
|
||||
top: '16px',
|
||||
},
|
||||
'&:hover > *': {
|
||||
visibility: 'visible',
|
||||
},
|
||||
});
|
||||
|
||||
export const CardItem = ({
|
||||
id,
|
||||
block,
|
||||
@@ -64,24 +91,44 @@ export const CardItem = ({
|
||||
}) => {
|
||||
const { addSubItem } = useKanban();
|
||||
const { openSubPage } = useRefPage();
|
||||
const [editable, setEditable] = useState(false);
|
||||
const showKanbanRefPageFlag = useFlag('ShowKanbanRefPage', false);
|
||||
const { editor } = useEditor();
|
||||
const { BlockRender } = useBlockRender();
|
||||
|
||||
const onAddItem = async () => {
|
||||
setEditable(true);
|
||||
await addSubItem(block);
|
||||
};
|
||||
|
||||
const onClickCard = async () => {
|
||||
showKanbanRefPageFlag && openSubPage(id);
|
||||
openSubPage(id);
|
||||
};
|
||||
|
||||
const onClickPen = (e: MouseEvent<Element>) => {
|
||||
e.stopPropagation();
|
||||
setEditable(true);
|
||||
editor.selectionManager.activeNodeByNodeId(block.id);
|
||||
};
|
||||
|
||||
return (
|
||||
<CardContainer onClick={onClickCard}>
|
||||
<CardContent>
|
||||
<RenderBlock blockId={id} />
|
||||
</CardContent>
|
||||
<CardActions onClick={onAddItem}>
|
||||
<PlusIcon />
|
||||
<span>Add a sub-block</span>
|
||||
</CardActions>
|
||||
</CardContainer>
|
||||
<MuiClickAwayListener onClickAway={() => setEditable(false)}>
|
||||
<CardContainer>
|
||||
<CardContent>
|
||||
<BlockRender blockId={id} />
|
||||
</CardContent>
|
||||
{showKanbanRefPageFlag && !editable && (
|
||||
<Overlay onClick={onClickCard}>
|
||||
<IconButton backgroundColor="#fff" onClick={onClickPen}>
|
||||
<PenIcon />
|
||||
</IconButton>
|
||||
</Overlay>
|
||||
)}
|
||||
<CardActions onClick={onAddItem}>
|
||||
<PlusIcon />
|
||||
<span>Add a sub-block</span>
|
||||
</CardActions>
|
||||
</CardContainer>
|
||||
</MuiClickAwayListener>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import { useEditor } from '@toeverything/components/editor-core';
|
||||
import { MuiBackdrop, styled, useTheme } from '@toeverything/components/ui';
|
||||
import { createContext, ReactNode, useContext, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
const Dialog = styled('div')({
|
||||
flex: 1,
|
||||
width: '880px',
|
||||
margin: '72px auto',
|
||||
background: '#fff',
|
||||
boxShadow: '0px 1px 10px rgba(152, 172, 189, 0.6)',
|
||||
borderRadius: '10px',
|
||||
padding: '72px 120px',
|
||||
overflow: 'scroll',
|
||||
});
|
||||
|
||||
const Modal = ({ open, children }: { open: boolean; children?: ReactNode }) => {
|
||||
const theme = useTheme();
|
||||
const { closeSubPage } = useRefPage();
|
||||
|
||||
return createPortal(
|
||||
<MuiBackdrop
|
||||
open={open}
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
background: 'rgba(58, 76, 92, 0.4)',
|
||||
zIndex: theme.affine.zIndex.popover,
|
||||
}}
|
||||
onClick={closeSubPage}
|
||||
>
|
||||
<Dialog
|
||||
onClick={(e: { stopPropagation: () => void }) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Dialog>
|
||||
</MuiBackdrop>,
|
||||
|
||||
document.body
|
||||
);
|
||||
};
|
||||
|
||||
const ModalPage = ({ blockId }: { blockId: string | null }) => {
|
||||
const { editor, editorElement } = useEditor();
|
||||
|
||||
const AffineEditor = editorElement as any;
|
||||
|
||||
return (
|
||||
<Modal open={!!blockId}>
|
||||
{blockId && (
|
||||
<AffineEditor
|
||||
workspace={editor.workspace}
|
||||
rootBlockId={blockId}
|
||||
scrollBlank={false}
|
||||
// use edgeless mode prevent padding and blank bottom
|
||||
isEdgeless
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
const RefPageContext = createContext<
|
||||
ReturnType<typeof useState<string | null>> | undefined
|
||||
>(undefined);
|
||||
|
||||
export const RefPageProvider = ({ children }: { children: ReactNode }) => {
|
||||
const state = useState<string | null>();
|
||||
const [blockId, setBlockId] = state;
|
||||
|
||||
return (
|
||||
<RefPageContext.Provider value={state}>
|
||||
{children}
|
||||
<ModalPage blockId={blockId ?? null} />
|
||||
</RefPageContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useRefPage = () => {
|
||||
const context = useContext(RefPageContext);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'Wrap your app inside of a `SubPageProvider` to have access to the hook context!'
|
||||
);
|
||||
}
|
||||
const [blockId, setBlockId] = context;
|
||||
const openSubPage = (blockId: string) => {
|
||||
setBlockId(blockId);
|
||||
};
|
||||
const closeSubPage = () => {
|
||||
setBlockId(null);
|
||||
};
|
||||
|
||||
return { blockId, open: !!blockId, openSubPage, closeSubPage };
|
||||
};
|
||||
|
||||
// export const openSubPage = () => {};
|
||||
@@ -4,30 +4,33 @@ import { SceneKanbanContext } from './context';
|
||||
import { CardContainerWrapper } from './dndable/wrapper/CardContainerWrapper';
|
||||
import type { ComponentType } from 'react';
|
||||
import type { CreateView } from '@toeverything/framework/virgo';
|
||||
import { RefPageProvider } from './RefPage';
|
||||
|
||||
export const SceneKanban: ComponentType<CreateView> = withKanban<CreateView>(
|
||||
({ editor, block }) => {
|
||||
const { kanban } = useKanban();
|
||||
|
||||
return (
|
||||
<SceneKanbanContext.Provider value={{ editor, block }}>
|
||||
<CardContainerWrapper
|
||||
dataSource={kanban}
|
||||
render={({
|
||||
activeId,
|
||||
items,
|
||||
containerIds,
|
||||
isSortingContainer,
|
||||
}) => (
|
||||
<CardContainer
|
||||
activeId={activeId}
|
||||
items={items}
|
||||
isSortingContainer={isSortingContainer}
|
||||
containerIds={containerIds}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</SceneKanbanContext.Provider>
|
||||
<RefPageProvider>
|
||||
<SceneKanbanContext.Provider value={{ editor, block }}>
|
||||
<CardContainerWrapper
|
||||
dataSource={kanban}
|
||||
render={({
|
||||
activeId,
|
||||
items,
|
||||
containerIds,
|
||||
isSortingContainer,
|
||||
}) => (
|
||||
<CardContainer
|
||||
activeId={activeId}
|
||||
items={items}
|
||||
isSortingContainer={isSortingContainer}
|
||||
containerIds={containerIds}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</SceneKanbanContext.Provider>
|
||||
</RefPageProvider>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ import { getRandomString } from '@toeverything/components/common';
|
||||
|
||||
export class ImageBlock extends BaseView {
|
||||
public override selectable = true;
|
||||
public override activatable = false;
|
||||
public override editable = false;
|
||||
type = Protocol.Block.Type.image;
|
||||
View = ImageView;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { TextProps } from '@toeverything/components/common';
|
||||
import {
|
||||
ContentColumnValue,
|
||||
services,
|
||||
Protocol,
|
||||
services,
|
||||
} from '@toeverything/datasource/db-service';
|
||||
import { type CreateView } from '@toeverything/framework/virgo';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
@@ -11,18 +11,17 @@ import {
|
||||
type ExtendedTextUtils,
|
||||
} from '../../components/text-manage';
|
||||
import { tabBlock } from '../../utils/indent';
|
||||
import { IndentWrapper } from '../../components/IndentWrapper';
|
||||
import type { Numbered, NumberedAsyncBlock } from './types';
|
||||
|
||||
import { getChildrenType, getNumber } from './data';
|
||||
import {
|
||||
supportChildren,
|
||||
RenderBlockChildren,
|
||||
useOnSelect,
|
||||
BlockPendantProvider,
|
||||
RenderBlockChildren,
|
||||
supportChildren,
|
||||
useOnSelect,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { List } from '../../components/style-container';
|
||||
import { BlockContainer } from '../../components/BlockContainer';
|
||||
import { List } from '../../components/style-container';
|
||||
import { getChildrenType, getNumber } from './data';
|
||||
|
||||
export const defaultTodoProps: Numbered = {
|
||||
text: { value: [{ text: '' }] },
|
||||
@@ -204,9 +203,7 @@ export const NumberedView = ({ block, editor }: CreateView) => {
|
||||
</List>
|
||||
</BlockPendantProvider>
|
||||
|
||||
<IndentWrapper>
|
||||
<RenderBlockChildren block={block} />
|
||||
</IndentWrapper>
|
||||
<RenderBlockChildren block={block} />
|
||||
</BlockContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import {
|
||||
AsyncBlock,
|
||||
BaseView,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { defaultTodoProps, NumberedView } from './NumberedView';
|
||||
import {
|
||||
Block2HtmlProps,
|
||||
commonBlock2HtmlContent,
|
||||
commonHTML2block,
|
||||
} from '../../utils/commonBlockClip';
|
||||
import { defaultTodoProps, NumberedView } from './NumberedView';
|
||||
|
||||
export class NumberedBlock extends BaseView {
|
||||
public type = Protocol.Block.Type.numbered;
|
||||
|
||||
@@ -12,7 +12,6 @@ import { styled } from '@toeverything/components/ui';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import { BlockContainer } from '../../components/BlockContainer';
|
||||
import { IndentWrapper } from '../../components/IndentWrapper';
|
||||
import { TextManage } from '../../components/text-manage';
|
||||
import { dedentBlock, tabBlock } from '../../utils/indent';
|
||||
interface CreateTextView extends CreateView {
|
||||
@@ -255,9 +254,7 @@ export const TextView = ({
|
||||
handleTab={onTab}
|
||||
/>
|
||||
</BlockPendantProvider>
|
||||
<IndentWrapper>
|
||||
<RenderBlockChildren block={block} />
|
||||
</IndentWrapper>
|
||||
<RenderBlockChildren block={block} />
|
||||
</BlockContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import { TextProps } from '@toeverything/components/common';
|
||||
import {
|
||||
AsyncBlock,
|
||||
BlockPendantProvider,
|
||||
CreateView,
|
||||
useOnSelect,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
import {
|
||||
ContentColumnValue,
|
||||
Protocol,
|
||||
} from '@toeverything/datasource/db-service';
|
||||
import { AsyncBlock, type CreateView } from '@toeverything/framework/virgo';
|
||||
import { useRef } from 'react';
|
||||
import { useRef, useState } from 'react';
|
||||
import { BlockContainer } from '../../components/BlockContainer';
|
||||
import {
|
||||
TextManage,
|
||||
type ExtendedTextUtils,
|
||||
@@ -36,6 +42,10 @@ const todoIsEmpty = (contentValue: ContentColumnValue): boolean => {
|
||||
export const TodoView = ({ block, editor }: CreateView) => {
|
||||
const properties = { ...defaultTodoProps, ...block.getProperties() };
|
||||
const text_ref = useRef<ExtendedTextUtils>(null);
|
||||
const [isSelect, setIsSelect] = useState<boolean>(false);
|
||||
useOnSelect(block.id, (isSelect: boolean) => {
|
||||
setIsSelect(isSelect);
|
||||
});
|
||||
|
||||
const turn_into_text_block = async () => {
|
||||
// Convert to text block
|
||||
@@ -121,28 +131,34 @@ export const TodoView = ({ block, editor }: CreateView) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<TodoBlock>
|
||||
<div className={'checkBoxContainer'}>
|
||||
<CheckBox
|
||||
checked={properties.checked?.value}
|
||||
onChange={on_checked_change}
|
||||
/>
|
||||
</div>
|
||||
<BlockContainer editor={editor} block={block} selected={isSelect}>
|
||||
<BlockPendantProvider block={block}>
|
||||
<TodoBlock>
|
||||
<div className={'checkBoxContainer'}>
|
||||
<CheckBox
|
||||
checked={properties.checked?.value}
|
||||
onChange={on_checked_change}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={'textContainer'}>
|
||||
<TextManage
|
||||
className={properties.checked?.value ? 'checked' : ''}
|
||||
ref={text_ref}
|
||||
editor={editor}
|
||||
block={block}
|
||||
supportMarkdown
|
||||
placeholder="To-do"
|
||||
handleEnter={on_text_enter}
|
||||
handleBackSpace={on_backspace}
|
||||
handleTab={on_tab}
|
||||
/>
|
||||
</div>
|
||||
</TodoBlock>
|
||||
<div className={'textContainer'}>
|
||||
<TextManage
|
||||
className={
|
||||
properties.checked?.value ? 'checked' : ''
|
||||
}
|
||||
ref={text_ref}
|
||||
editor={editor}
|
||||
block={block}
|
||||
supportMarkdown
|
||||
placeholder="To-do"
|
||||
handleEnter={on_text_enter}
|
||||
handleBackSpace={on_backspace}
|
||||
handleTab={on_tab}
|
||||
/>
|
||||
</div>
|
||||
</TodoBlock>
|
||||
</BlockPendantProvider>
|
||||
</BlockContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import {
|
||||
BaseView,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
withTreeViewChildren,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { withTreeViewChildren } from '../../utils/WithTreeViewChildren';
|
||||
import { TodoView, defaultTodoProps } from './TodoView';
|
||||
import type { TodoAsyncBlock } from './types';
|
||||
import { defaultTodoProps, TodoView } from './TodoView';
|
||||
|
||||
import {
|
||||
Block2HtmlProps,
|
||||
commonBlock2HtmlContent,
|
||||
commonHTML2block,
|
||||
} from '../../utils/commonBlockClip';
|
||||
import type { TodoAsyncBlock } from './types';
|
||||
|
||||
export class TodoBlock extends BaseView {
|
||||
type = Protocol.Block.Type.todo;
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
|
||||
export class YoutubeBlock extends BaseView {
|
||||
public override selectable = true;
|
||||
public override activatable = false;
|
||||
public override editable = false;
|
||||
type = Protocol.Block.Type.youtube;
|
||||
View = YoutubeView;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export const BlockContainer = function ({
|
||||
);
|
||||
};
|
||||
|
||||
export const Container = styled('div')<{ selected: boolean }>(
|
||||
export const Container = styled('div')<{ selected?: boolean }>(
|
||||
({ selected, theme }) => ({
|
||||
backgroundColor: selected ? theme.affine.palette.textSelected : '',
|
||||
marginBottom: '2px',
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { ChildrenView } from '@toeverything/framework/virgo';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
|
||||
/**
|
||||
* Indent rendering child nodes
|
||||
*/
|
||||
export const IndentWrapper = (props: PropsWithChildren) => {
|
||||
return <StyledIdentWrapper>{props.children}</StyledIdentWrapper>;
|
||||
};
|
||||
|
||||
const StyledIdentWrapper = styled('div')({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
// TODO: marginLeft should use theme provided by styled
|
||||
marginLeft: '30px',
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
export * from './IndentWrapper';
|
||||
@@ -1,9 +1,9 @@
|
||||
import { memo, useEffect, useRef, useState } from 'react';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { memo, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { StyledBlockPreview } from '@toeverything/components/common';
|
||||
import { AsyncBlock, useEditor } from '@toeverything/components/editor-core';
|
||||
import { services } from '@toeverything/datasource/db-service';
|
||||
import { AsyncBlock } from '@toeverything/framework/virgo';
|
||||
import { debounce, sleep } from '@toeverything/utils';
|
||||
|
||||
const updateTitle = async (
|
||||
@@ -73,15 +73,15 @@ const useBlockTitle = (block: AsyncBlock, blockId: string) => {
|
||||
type BlockPreviewProps = {
|
||||
block: AsyncBlock;
|
||||
blockId: string;
|
||||
editorElement?: () => JSX.Element;
|
||||
};
|
||||
|
||||
const InternalBlockPreview = (props: BlockPreviewProps) => {
|
||||
const container = useRef<HTMLDivElement>();
|
||||
const [preview, setPreview] = useState(true);
|
||||
const title = useBlockTitle(props.block, props.blockId);
|
||||
const { editorElement } = useEditor();
|
||||
|
||||
const AffineEditor = props.editorElement as any;
|
||||
const AffineEditor = editorElement as any;
|
||||
|
||||
useEffect(() => {
|
||||
if (container?.current) {
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import {
|
||||
AsyncBlock,
|
||||
useCurrentView,
|
||||
useLazyIframe,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
import { ReactElement, ReactNode, useEffect, useRef, useState } from 'react';
|
||||
import { ReactNode, useEffect, useRef, useState } from 'react';
|
||||
import { SCENE_CONFIG } from '../../blocks/group/config';
|
||||
import { BlockPreview } from './BlockView';
|
||||
import { formatUrl } from './format-url';
|
||||
|
||||
export interface Props {
|
||||
block: AsyncBlock;
|
||||
editorElement?: () => JSX.Element;
|
||||
viewType?: string;
|
||||
link: string;
|
||||
// onResizeEnd: (data: any) => void;
|
||||
@@ -150,7 +148,7 @@ const LoadingContiner = () => {
|
||||
};
|
||||
|
||||
export const SourceView = (props: Props) => {
|
||||
const { link, isSelected, block, editorElement } = props;
|
||||
const { link, isSelected, block } = props;
|
||||
const src = formatUrl(link);
|
||||
// let iframeShow = useLazyIframe(src, 3000, iframeContainer);
|
||||
const [currentView] = useCurrentView();
|
||||
@@ -161,10 +159,7 @@ export const SourceView = (props: Props) => {
|
||||
<SourceViewContainer isSelected={isSelected} scene={type}>
|
||||
<MouseMaskContainer />
|
||||
|
||||
<LazyIframe
|
||||
src={src}
|
||||
fallback={LoadingContiner()}
|
||||
></LazyIframe>
|
||||
<LazyIframe src={src} fallback={LoadingContiner()} />
|
||||
</SourceViewContainer>
|
||||
</div>
|
||||
);
|
||||
@@ -175,11 +170,7 @@ export const SourceView = (props: Props) => {
|
||||
style={{ padding: '0' }}
|
||||
scene={type}
|
||||
>
|
||||
<BlockPreview
|
||||
block={block}
|
||||
editorElement={editorElement}
|
||||
blockId={src}
|
||||
/>
|
||||
<BlockPreview block={block} blockId={src} />
|
||||
</SourceViewContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export const isYoutubeUrl = (url?: string): boolean => {
|
||||
if (!url) return false;
|
||||
const allowedHosts = ['www.youtu.be', 'www.youtube.com'];
|
||||
const host = new URL(url).host;
|
||||
return allowedHosts.includes(host);
|
||||
|
||||
@@ -1,236 +0,0 @@
|
||||
import {
|
||||
BlockPendantProvider,
|
||||
CreateView,
|
||||
RenderBlock,
|
||||
useCurrentView,
|
||||
useOnSelect,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
import type {
|
||||
ComponentPropsWithoutRef,
|
||||
ComponentPropsWithRef,
|
||||
CSSProperties,
|
||||
ReactElement,
|
||||
} from 'react';
|
||||
import { forwardRef, useState } from 'react';
|
||||
import { SCENE_CONFIG } from '../blocks/group/config';
|
||||
import { BlockContainer } from '../components/BlockContainer';
|
||||
|
||||
type WithChildrenConfig = {
|
||||
indent: CSSProperties['marginLeft'];
|
||||
};
|
||||
|
||||
const defaultConfig: WithChildrenConfig = {
|
||||
indent: '30px',
|
||||
};
|
||||
|
||||
const TreeView = forwardRef<
|
||||
HTMLDivElement,
|
||||
{ lastItem?: boolean } & ComponentPropsWithRef<'div'>
|
||||
>(({ lastItem = false, children, onClick, ...restProps }, ref) => {
|
||||
return (
|
||||
<TreeWrapper ref={ref} {...restProps}>
|
||||
<StyledTreeView>
|
||||
<VerticalLine last={lastItem} onClick={onClick} />
|
||||
<HorizontalLine last={lastItem} onClick={onClick} />
|
||||
{lastItem && <LastItemRadius />}
|
||||
</StyledTreeView>
|
||||
{/* maybe need a child wrapper */}
|
||||
{children}
|
||||
</TreeWrapper>
|
||||
);
|
||||
});
|
||||
|
||||
interface ChildrenViewProp {
|
||||
childrenIds: string[];
|
||||
handleCollapse: () => void;
|
||||
indent?: string | number;
|
||||
}
|
||||
|
||||
const ChildrenView = ({
|
||||
childrenIds,
|
||||
handleCollapse,
|
||||
indent,
|
||||
}: ChildrenViewProp) => {
|
||||
const [currentView] = useCurrentView();
|
||||
const isKanbanScene = currentView.type === SCENE_CONFIG.KANBAN;
|
||||
|
||||
return (
|
||||
<Children style={{ ...(!isKanbanScene && { marginLeft: indent }) }}>
|
||||
{childrenIds.map((childId, idx) => {
|
||||
if (isKanbanScene) {
|
||||
return (
|
||||
<StyledBorder key={childId}>
|
||||
<RenderBlock blockId={childId} />
|
||||
</StyledBorder>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<TreeView
|
||||
key={childId}
|
||||
lastItem={idx === childrenIds.length - 1}
|
||||
onClick={handleCollapse}
|
||||
>
|
||||
<RenderBlock key={childId} blockId={childId} />
|
||||
</TreeView>
|
||||
);
|
||||
})}
|
||||
</Children>
|
||||
);
|
||||
};
|
||||
|
||||
const CollapsedNode = forwardRef<
|
||||
HTMLDivElement,
|
||||
ComponentPropsWithoutRef<'div'>
|
||||
>((props, ref) => {
|
||||
return (
|
||||
<TreeView ref={ref} lastItem={true} {...props}>
|
||||
<Collapsed onClick={props.onClick}>···</Collapsed>
|
||||
</TreeView>
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Indent rendering child nodes
|
||||
*/
|
||||
export const withTreeViewChildren = (
|
||||
creator: (props: CreateView) => ReactElement,
|
||||
customConfig: Partial<WithChildrenConfig> = {}
|
||||
) => {
|
||||
const config = {
|
||||
...defaultConfig,
|
||||
...customConfig,
|
||||
};
|
||||
|
||||
return (props: CreateView) => {
|
||||
const { block, editor } = props;
|
||||
const collapsed = block.getProperty('collapsed')?.value;
|
||||
const childrenIds = block.childrenIds;
|
||||
const showChildren = !collapsed && childrenIds.length > 0;
|
||||
|
||||
const [isSelect, setIsSelect] = useState<boolean>(false);
|
||||
useOnSelect(block.id, (isSelect: boolean) => {
|
||||
setIsSelect(isSelect);
|
||||
});
|
||||
const handleCollapse = () => {
|
||||
block.setProperty('collapsed', { value: true });
|
||||
};
|
||||
|
||||
const handleExpand = () => {
|
||||
block.setProperty('collapsed', { value: false });
|
||||
};
|
||||
|
||||
return (
|
||||
<BlockContainer
|
||||
editor={props.editor}
|
||||
block={block}
|
||||
selected={isSelect}
|
||||
className={Wrapper.toString()}
|
||||
>
|
||||
<BlockPendantProvider block={block}>
|
||||
<div>{creator(props)}</div>
|
||||
</BlockPendantProvider>
|
||||
|
||||
{collapsed && (
|
||||
<CollapsedNode
|
||||
onClick={handleExpand}
|
||||
style={{ marginLeft: config.indent }}
|
||||
/>
|
||||
)}
|
||||
{showChildren && (
|
||||
<ChildrenView
|
||||
childrenIds={childrenIds}
|
||||
handleCollapse={handleCollapse}
|
||||
indent={config.indent}
|
||||
/>
|
||||
)}
|
||||
</BlockContainer>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
const Wrapper = styled('div')({ display: 'flex', flexDirection: 'column' });
|
||||
|
||||
const Children = Wrapper;
|
||||
|
||||
const TREE_COLOR = '#D5DFE6';
|
||||
// adjust left and right margins of the the tree line
|
||||
const TREE_LINE_LEFT_OFFSET = '-16px';
|
||||
// determine the position of the horizontal line by the type of the item
|
||||
const TREE_LINE_TOP_OFFSET = '20px'; // '50%'
|
||||
const TREE_LINE_WIDTH = '12px';
|
||||
|
||||
const TreeWrapper = styled('div')({
|
||||
position: 'relative',
|
||||
});
|
||||
|
||||
const StyledTreeView = styled('div')({
|
||||
position: 'absolute',
|
||||
left: TREE_LINE_LEFT_OFFSET,
|
||||
height: '100%',
|
||||
});
|
||||
|
||||
const Line = styled('div')({
|
||||
position: 'absolute',
|
||||
cursor: 'pointer',
|
||||
backgroundColor: TREE_COLOR,
|
||||
// somehow tldraw would override this
|
||||
boxSizing: 'content-box!important' as any,
|
||||
// See [Can I add background color only for padding?](https://stackoverflow.com/questions/14628601/can-i-add-background-color-only-for-padding)
|
||||
backgroundClip: 'content-box',
|
||||
backgroundOrigin: 'content-box',
|
||||
// Increase click hot spot
|
||||
padding: '10px',
|
||||
});
|
||||
|
||||
const VerticalLine = styled(Line)<{ last: boolean }>(({ last }) => ({
|
||||
width: '1px',
|
||||
height: last ? TREE_LINE_TOP_OFFSET : '100%',
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
transform: 'translate(-50%, 0)',
|
||||
|
||||
opacity: last ? 0 : 'unset',
|
||||
}));
|
||||
|
||||
const HorizontalLine = styled(Line)<{ last: boolean }>(({ last }) => ({
|
||||
width: TREE_LINE_WIDTH,
|
||||
height: '1px',
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0,
|
||||
top: TREE_LINE_TOP_OFFSET,
|
||||
transform: 'translate(0, -50%)',
|
||||
opacity: last ? 0 : 'unset',
|
||||
}));
|
||||
|
||||
const Collapsed = styled('div')({
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
color: '#98ACBD',
|
||||
padding: '8px',
|
||||
});
|
||||
|
||||
const LastItemRadius = styled('div')({
|
||||
boxSizing: 'content-box',
|
||||
position: 'absolute',
|
||||
left: '-0.5px',
|
||||
top: 0,
|
||||
height: TREE_LINE_TOP_OFFSET,
|
||||
bottom: '50%',
|
||||
width: TREE_LINE_WIDTH,
|
||||
borderWidth: '1px',
|
||||
borderStyle: 'solid',
|
||||
borderLeftColor: TREE_COLOR,
|
||||
borderBottomColor: TREE_COLOR,
|
||||
borderTop: 'none',
|
||||
borderRight: 'none',
|
||||
borderRadius: '0 0 0 3px',
|
||||
pointerEvents: 'none',
|
||||
});
|
||||
|
||||
const StyledBorder = styled('div')({
|
||||
border: '1px solid #E0E6EB',
|
||||
borderRadius: '5px',
|
||||
margin: '4px',
|
||||
});
|
||||
Reference in New Issue
Block a user