refactor: update block
This commit is contained in:
@@ -1,29 +1,28 @@
|
|||||||
import type { TextProps } from '@toeverything/components/common';
|
import type { TextProps } from '@toeverything/components/common';
|
||||||
import {
|
import {
|
||||||
ContentColumnValue,
|
ContentColumnValue,
|
||||||
services,
|
|
||||||
Protocol,
|
Protocol,
|
||||||
|
services,
|
||||||
} from '@toeverything/datasource/db-service';
|
} from '@toeverything/datasource/db-service';
|
||||||
import { type CreateView } from '@toeverything/framework/virgo';
|
import { type CreateView } from '@toeverything/framework/virgo';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
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 {
|
import {
|
||||||
TextManage,
|
TextManage,
|
||||||
type ExtendedTextUtils,
|
type ExtendedTextUtils,
|
||||||
} from '../../components/text-manage';
|
} from '../../components/text-manage';
|
||||||
import { tabBlock } from '../../utils/indent';
|
import { tabBlock } from '../../utils/indent';
|
||||||
|
import { BulletIcon, getChildrenType, NumberType } from './data';
|
||||||
import { BulletBlock, BulletProperties } from './types';
|
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 = {
|
export const defaultBulletProps: BulletProperties = {
|
||||||
text: { value: [{ text: '' }] },
|
text: { value: [{ text: '' }] },
|
||||||
@@ -208,9 +207,7 @@ export const BulletView = ({ block, editor }: CreateView) => {
|
|||||||
</div>
|
</div>
|
||||||
</List>
|
</List>
|
||||||
</BlockPendantProvider>
|
</BlockPendantProvider>
|
||||||
<IndentWrapper>
|
|
||||||
<RenderBlockChildren block={block} />
|
<RenderBlockChildren block={block} />
|
||||||
</IndentWrapper>
|
|
||||||
</BlockContainer>
|
</BlockContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
|
import {
|
||||||
|
DefaultColumnsValue,
|
||||||
|
Protocol,
|
||||||
|
} from '@toeverything/datasource/db-service';
|
||||||
import {
|
import {
|
||||||
AsyncBlock,
|
AsyncBlock,
|
||||||
BaseView,
|
BaseView,
|
||||||
CreateView,
|
getTextHtml,
|
||||||
getTextProperties,
|
getTextProperties,
|
||||||
SelectBlock,
|
SelectBlock,
|
||||||
getTextHtml,
|
|
||||||
} from '@toeverything/framework/virgo';
|
} from '@toeverything/framework/virgo';
|
||||||
import {
|
|
||||||
Protocol,
|
|
||||||
DefaultColumnsValue,
|
|
||||||
} from '@toeverything/datasource/db-service';
|
|
||||||
// import { withTreeViewChildren } from '../../utils/with-tree-view-children';
|
// import { withTreeViewChildren } from '../../utils/with-tree-view-children';
|
||||||
import { defaultBulletProps, BulletView } from './BulletView';
|
import { BulletView, defaultBulletProps } from './BulletView';
|
||||||
import { IndentWrapper } from '../../components/IndentWrapper';
|
|
||||||
|
|
||||||
export class BulletBlock extends BaseView {
|
export class BulletBlock extends BaseView {
|
||||||
public type = Protocol.Block.Type.bullet;
|
public type = Protocol.Block.Type.bullet;
|
||||||
|
|||||||
@@ -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';
|
import { ChildrenView, CreateView } from '@toeverything/framework/virgo';
|
||||||
|
|
||||||
export const GridItemRender = function (
|
export const GridItemRender = function (
|
||||||
@@ -6,10 +6,11 @@ export const GridItemRender = function (
|
|||||||
) {
|
) {
|
||||||
const GridItem = function (props: CreateView) {
|
const GridItem = function (props: CreateView) {
|
||||||
const { block } = props;
|
const { block } = props;
|
||||||
|
const { BlockRender } = useBlockRender();
|
||||||
const children = (
|
const children = (
|
||||||
<>
|
<>
|
||||||
{block.childrenIds.map(id => {
|
{block.childrenIds.map(id => {
|
||||||
return <RenderBlock key={id} blockId={id} />;
|
return <BlockRender key={id} blockId={id} />;
|
||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { RenderBlock } from '@toeverything/components/editor-core';
|
import { useBlockRender } from '@toeverything/components/editor-core';
|
||||||
import { CreateView } from '@toeverything/framework/virgo';
|
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
|
||||||
import { GridHandle } from './GirdHandle';
|
|
||||||
import { styled } from '@toeverything/components/ui';
|
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 ReactDOM from 'react-dom';
|
||||||
import {
|
import {
|
||||||
GRID_ITEM_CLASS_NAME,
|
GRID_ITEM_CLASS_NAME,
|
||||||
GRID_ITEM_CONTENT_CLASS_NAME,
|
GRID_ITEM_CONTENT_CLASS_NAME,
|
||||||
} from '../grid-item/GridItem';
|
} from '../grid-item/GridItem';
|
||||||
import { debounce, domToRect, Point } from '@toeverything/utils';
|
import { GridHandle } from './GirdHandle';
|
||||||
import clsx from 'clsx';
|
|
||||||
import { Protocol } from '@toeverything/datasource/db-service';
|
|
||||||
|
|
||||||
const DB_UPDATE_DELAY = 50;
|
const DB_UPDATE_DELAY = 50;
|
||||||
const GRID_ON_DRAG_CLASS = 'grid-layout-on-drag';
|
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 originalLeftWidth = useRef<number>(gridItemMinWidth);
|
||||||
const originalRightWidth = useRef<number>(gridItemMinWidth);
|
const originalRightWidth = useRef<number>(gridItemMinWidth);
|
||||||
const [alertHandleId, setAlertHandleId] = useState<string>(null);
|
const [alertHandleId, setAlertHandleId] = useState<string>(null);
|
||||||
|
const { BlockRender } = useBlockRender();
|
||||||
|
|
||||||
const getLeftRightGridItemDomByIndex = (index: number) => {
|
const getLeftRightGridItemDomByIndex = (index: number) => {
|
||||||
const gridItems = Array.from(gridContainerRef.current?.children).filter(
|
const gridItems = Array.from(gridContainerRef.current?.children).filter(
|
||||||
@@ -226,7 +227,7 @@ export const Grid = function (props: CreateView) {
|
|||||||
key={id}
|
key={id}
|
||||||
className={GRID_ITEM_CLASS_NAME}
|
className={GRID_ITEM_CLASS_NAME}
|
||||||
>
|
>
|
||||||
<RenderBlock hasContainer={false} blockId={id} />
|
<BlockRender hasContainer={false} blockId={id} />
|
||||||
<GridHandle
|
<GridHandle
|
||||||
onDrag={event => handleDragGrid(event, i)}
|
onDrag={event => handleDragGrid(event, i)}
|
||||||
editor={editor}
|
editor={editor}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ import { RenderBlockChildren } from '@toeverything/components/editor-core';
|
|||||||
import type { CreateView } from '@toeverything/framework/virgo';
|
import type { CreateView } from '@toeverything/framework/virgo';
|
||||||
|
|
||||||
export const ScenePage = ({ block }: CreateView) => {
|
export const ScenePage = ({ block }: CreateView) => {
|
||||||
return <RenderBlockChildren block={block} />;
|
return <RenderBlockChildren block={block} indent={false} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
KanbanCard,
|
KanbanCard,
|
||||||
RenderBlock,
|
useBlockRender,
|
||||||
useEditor,
|
useEditor,
|
||||||
useKanban,
|
useKanban,
|
||||||
} from '@toeverything/components/editor-core';
|
} from '@toeverything/components/editor-core';
|
||||||
@@ -94,6 +94,7 @@ export const CardItem = ({
|
|||||||
const [editable, setEditable] = useState(false);
|
const [editable, setEditable] = useState(false);
|
||||||
const showKanbanRefPageFlag = useFlag('ShowKanbanRefPage', false);
|
const showKanbanRefPageFlag = useFlag('ShowKanbanRefPage', false);
|
||||||
const { editor } = useEditor();
|
const { editor } = useEditor();
|
||||||
|
const { BlockRender } = useBlockRender();
|
||||||
|
|
||||||
const onAddItem = async () => {
|
const onAddItem = async () => {
|
||||||
setEditable(true);
|
setEditable(true);
|
||||||
@@ -114,7 +115,7 @@ export const CardItem = ({
|
|||||||
<MuiClickAwayListener onClickAway={() => setEditable(false)}>
|
<MuiClickAwayListener onClickAway={() => setEditable(false)}>
|
||||||
<CardContainer>
|
<CardContainer>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<RenderBlock blockId={id} />
|
<BlockRender blockId={id} />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
{showKanbanRefPageFlag && !editable && (
|
{showKanbanRefPageFlag && !editable && (
|
||||||
<Overlay onClick={onClickCard}>
|
<Overlay onClick={onClickCard}>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { TextProps } from '@toeverything/components/common';
|
import { TextProps } from '@toeverything/components/common';
|
||||||
import {
|
import {
|
||||||
ContentColumnValue,
|
ContentColumnValue,
|
||||||
services,
|
|
||||||
Protocol,
|
Protocol,
|
||||||
|
services,
|
||||||
} from '@toeverything/datasource/db-service';
|
} from '@toeverything/datasource/db-service';
|
||||||
import { type CreateView } from '@toeverything/framework/virgo';
|
import { type CreateView } from '@toeverything/framework/virgo';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
@@ -11,18 +11,17 @@ import {
|
|||||||
type ExtendedTextUtils,
|
type ExtendedTextUtils,
|
||||||
} from '../../components/text-manage';
|
} from '../../components/text-manage';
|
||||||
import { tabBlock } from '../../utils/indent';
|
import { tabBlock } from '../../utils/indent';
|
||||||
import { IndentWrapper } from '../../components/IndentWrapper';
|
|
||||||
import type { Numbered, NumberedAsyncBlock } from './types';
|
import type { Numbered, NumberedAsyncBlock } from './types';
|
||||||
|
|
||||||
import { getChildrenType, getNumber } from './data';
|
|
||||||
import {
|
import {
|
||||||
supportChildren,
|
|
||||||
RenderBlockChildren,
|
|
||||||
useOnSelect,
|
|
||||||
BlockPendantProvider,
|
BlockPendantProvider,
|
||||||
|
RenderBlockChildren,
|
||||||
|
supportChildren,
|
||||||
|
useOnSelect,
|
||||||
} from '@toeverything/components/editor-core';
|
} from '@toeverything/components/editor-core';
|
||||||
import { List } from '../../components/style-container';
|
|
||||||
import { BlockContainer } from '../../components/BlockContainer';
|
import { BlockContainer } from '../../components/BlockContainer';
|
||||||
|
import { List } from '../../components/style-container';
|
||||||
|
import { getChildrenType, getNumber } from './data';
|
||||||
|
|
||||||
export const defaultTodoProps: Numbered = {
|
export const defaultTodoProps: Numbered = {
|
||||||
text: { value: [{ text: '' }] },
|
text: { value: [{ text: '' }] },
|
||||||
@@ -204,9 +203,7 @@ export const NumberedView = ({ block, editor }: CreateView) => {
|
|||||||
</List>
|
</List>
|
||||||
</BlockPendantProvider>
|
</BlockPendantProvider>
|
||||||
|
|
||||||
<IndentWrapper>
|
|
||||||
<RenderBlockChildren block={block} />
|
<RenderBlockChildren block={block} />
|
||||||
</IndentWrapper>
|
|
||||||
</BlockContainer>
|
</BlockContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
|
import {
|
||||||
|
DefaultColumnsValue,
|
||||||
|
Protocol,
|
||||||
|
} from '@toeverything/datasource/db-service';
|
||||||
import {
|
import {
|
||||||
AsyncBlock,
|
AsyncBlock,
|
||||||
BaseView,
|
BaseView,
|
||||||
|
getTextHtml,
|
||||||
getTextProperties,
|
getTextProperties,
|
||||||
SelectBlock,
|
SelectBlock,
|
||||||
getTextHtml,
|
|
||||||
} from '@toeverything/framework/virgo';
|
} from '@toeverything/framework/virgo';
|
||||||
import {
|
|
||||||
Protocol,
|
|
||||||
DefaultColumnsValue,
|
|
||||||
} from '@toeverything/datasource/db-service';
|
|
||||||
// import { withTreeViewChildren } from '../../utils/with-tree-view-children';
|
// import { withTreeViewChildren } from '../../utils/with-tree-view-children';
|
||||||
import { defaultTodoProps, NumberedView } from './NumberedView';
|
import { defaultTodoProps, NumberedView } from './NumberedView';
|
||||||
import { IndentWrapper } from '../../components/IndentWrapper';
|
|
||||||
|
|
||||||
export class NumberedBlock extends BaseView {
|
export class NumberedBlock extends BaseView {
|
||||||
public type = Protocol.Block.Type.numbered;
|
public type = Protocol.Block.Type.numbered;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { styled } from '@toeverything/components/ui';
|
|||||||
import { Protocol } from '@toeverything/datasource/db-service';
|
import { Protocol } from '@toeverything/datasource/db-service';
|
||||||
import { CreateView } from '@toeverything/framework/virgo';
|
import { CreateView } from '@toeverything/framework/virgo';
|
||||||
import { BlockContainer } from '../../components/BlockContainer';
|
import { BlockContainer } from '../../components/BlockContainer';
|
||||||
import { IndentWrapper } from '../../components/IndentWrapper';
|
|
||||||
import { TextManage } from '../../components/text-manage';
|
import { TextManage } from '../../components/text-manage';
|
||||||
import { dedentBlock, tabBlock } from '../../utils/indent';
|
import { dedentBlock, tabBlock } from '../../utils/indent';
|
||||||
interface CreateTextView extends CreateView {
|
interface CreateTextView extends CreateView {
|
||||||
@@ -255,9 +254,7 @@ export const TextView = ({
|
|||||||
handleTab={onTab}
|
handleTab={onTab}
|
||||||
/>
|
/>
|
||||||
</BlockPendantProvider>
|
</BlockPendantProvider>
|
||||||
<IndentWrapper>
|
|
||||||
<RenderBlockChildren block={block} />
|
<RenderBlockChildren block={block} />
|
||||||
</IndentWrapper>
|
|
||||||
</BlockContainer>
|
</BlockContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
import { TextProps } from '@toeverything/components/common';
|
import { TextProps } from '@toeverything/components/common';
|
||||||
|
import {
|
||||||
|
AsyncBlock,
|
||||||
|
BlockPendantProvider,
|
||||||
|
CreateView,
|
||||||
|
useOnSelect,
|
||||||
|
} from '@toeverything/components/editor-core';
|
||||||
import { styled } from '@toeverything/components/ui';
|
import { styled } from '@toeverything/components/ui';
|
||||||
import {
|
import {
|
||||||
ContentColumnValue,
|
ContentColumnValue,
|
||||||
Protocol,
|
Protocol,
|
||||||
} from '@toeverything/datasource/db-service';
|
} from '@toeverything/datasource/db-service';
|
||||||
import { AsyncBlock, type CreateView } from '@toeverything/framework/virgo';
|
import { useRef, useState } from 'react';
|
||||||
import { useRef } from 'react';
|
import { BlockContainer } from '../../components/BlockContainer';
|
||||||
import {
|
import {
|
||||||
TextManage,
|
TextManage,
|
||||||
type ExtendedTextUtils,
|
type ExtendedTextUtils,
|
||||||
@@ -36,6 +42,10 @@ const todoIsEmpty = (contentValue: ContentColumnValue): boolean => {
|
|||||||
export const TodoView = ({ block, editor }: CreateView) => {
|
export const TodoView = ({ block, editor }: CreateView) => {
|
||||||
const properties = { ...defaultTodoProps, ...block.getProperties() };
|
const properties = { ...defaultTodoProps, ...block.getProperties() };
|
||||||
const text_ref = useRef<ExtendedTextUtils>(null);
|
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 () => {
|
const turn_into_text_block = async () => {
|
||||||
// Convert to text block
|
// Convert to text block
|
||||||
@@ -121,6 +131,8 @@ export const TodoView = ({ block, editor }: CreateView) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<BlockContainer editor={editor} block={block} selected={isSelect}>
|
||||||
|
<BlockPendantProvider block={block}>
|
||||||
<TodoBlock>
|
<TodoBlock>
|
||||||
<div className={'checkBoxContainer'}>
|
<div className={'checkBoxContainer'}>
|
||||||
<CheckBox
|
<CheckBox
|
||||||
@@ -131,7 +143,9 @@ export const TodoView = ({ block, editor }: CreateView) => {
|
|||||||
|
|
||||||
<div className={'textContainer'}>
|
<div className={'textContainer'}>
|
||||||
<TextManage
|
<TextManage
|
||||||
className={properties.checked?.value ? 'checked' : ''}
|
className={
|
||||||
|
properties.checked?.value ? 'checked' : ''
|
||||||
|
}
|
||||||
ref={text_ref}
|
ref={text_ref}
|
||||||
editor={editor}
|
editor={editor}
|
||||||
block={block}
|
block={block}
|
||||||
@@ -143,6 +157,8 @@ export const TodoView = ({ block, editor }: CreateView) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</TodoBlock>
|
</TodoBlock>
|
||||||
|
</BlockPendantProvider>
|
||||||
|
</BlockContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
BaseView,
|
|
||||||
getTextProperties,
|
|
||||||
AsyncBlock,
|
AsyncBlock,
|
||||||
SelectBlock,
|
BaseView,
|
||||||
getTextHtml,
|
getTextHtml,
|
||||||
} from '@toeverything/framework/virgo';
|
getTextProperties,
|
||||||
// import type { CreateView } from '@toeverything/framework/virgo';
|
SelectBlock,
|
||||||
|
withTreeViewChildren,
|
||||||
|
} from '@toeverything/components/editor-core';
|
||||||
import {
|
import {
|
||||||
Protocol,
|
|
||||||
DefaultColumnsValue,
|
DefaultColumnsValue,
|
||||||
|
Protocol,
|
||||||
} from '@toeverything/datasource/db-service';
|
} from '@toeverything/datasource/db-service';
|
||||||
// import { withTreeViewChildren } from '../../utils/with-tree-view-children';
|
import { defaultTodoProps, TodoView } from './TodoView';
|
||||||
import { withTreeViewChildren } from '../../utils/WithTreeViewChildren';
|
|
||||||
import { TodoView, defaultTodoProps } from './TodoView';
|
|
||||||
import type { TodoAsyncBlock } from './types';
|
import type { TodoAsyncBlock } from './types';
|
||||||
|
|
||||||
export class TodoBlock extends BaseView {
|
export class TodoBlock extends BaseView {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export const BlockContainer = function ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Container = styled('div')<{ selected: boolean }>(
|
export const Container = styled('div')<{ selected?: boolean }>(
|
||||||
({ selected, theme }) => ({
|
({ selected, theme }) => ({
|
||||||
backgroundColor: selected ? theme.affine.palette.textSelected : '',
|
backgroundColor: selected ? theme.affine.palette.textSelected : '',
|
||||||
marginBottom: '2px',
|
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,4 +1,5 @@
|
|||||||
export const isYoutubeUrl = (url?: string): boolean => {
|
export const isYoutubeUrl = (url?: string): boolean => {
|
||||||
|
if (!url) return false;
|
||||||
const allowedHosts = ['www.youtu.be', 'www.youtube.com'];
|
const allowedHosts = ['www.youtu.be', 'www.youtube.com'];
|
||||||
const host = new URL(url).host;
|
const host = new URL(url).host;
|
||||||
return allowedHosts.includes(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',
|
|
||||||
});
|
|
||||||
@@ -69,4 +69,5 @@ export function RenderBlock({
|
|||||||
|
|
||||||
const BlockContainer = styled('div')(({ theme }) => ({
|
const BlockContainer = styled('div')(({ theme }) => ({
|
||||||
fontSize: theme.typography.body1.fontSize,
|
fontSize: theme.typography.body1.fontSize,
|
||||||
|
flex: 1,
|
||||||
}));
|
}));
|
||||||
|
|||||||
Reference in New Issue
Block a user