Skip to content

Commit

Permalink
feat(outliner): add rough support for drag and drop
Browse files Browse the repository at this point in the history
  • Loading branch information
dragonman225 authored and thesophiaxu committed Apr 13, 2022
1 parent 825a4f5 commit aa75365
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 84 deletions.
147 changes: 74 additions & 73 deletions packages/unigraph-dev-explorer/src/examples/notes/NoteBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,79 +103,80 @@ const BlockChildren = ({

return (
<div style={{ width: '100%' }}>
{subentities.length || isChildren ? (
<DragandDrop
dndContext={tabContext.viewId}
listId={data?.uid}
arrayId={data?._value?.children?.uid}
style={dropIndicatorStyles}
transformOnDrop={(props: any) => {
return {
...props,
uid: undefined,
data: {
type: { 'unigraph.id': '$/schema/embed_block' },
_value: {
content: { uid: props.uid },
},
},
};
}}
>
{(subentities as PlainUnigraphObject[]).map((entity, index) => {
if (!entity?.uid) return undefined;
const { uid } = entity;
const isCollapsed = isChildrenCollapsed[uid];
return (
<Outline
key={uid}
object={entity}
index={index}
collapsed={isCollapsed}
setCollapsed={(val: boolean) => {
setIsChildrenCollapsed({
...isChildrenCollapsed,
[uid]: val,
});
}}
// createBelow={() => {
// addChild(data, editorContext, elindex);
// }}
displayAs={childrenDisplayAs}
parentDisplayAs={displayAs}
showCollapse={getSubentities(entity)[0].length >= 1}
>
<BlockChild
el={entity}
elindex={index}
editorContext={editorContext}
callbacks={getCallbacks(callbacks, data, editorContext, index)}
shortcuts={getShortcuts(data, editorContext, index, copyOrCutHandler, callbacks)}
isCollapsed={isCollapsed}
setCollapsed={(val: boolean) => {
setIsChildrenCollapsed({
...isChildrenCollapsed,
[uid]: val,
});
}}
displayAs={childrenDisplayAs}
/>
</Outline>
);
})}
</DragandDrop>
) : (
data && (
<Outline
object={data}
index={0}
displayAs={data?._value?.children?._displayAs || 'outliner'}
parentDisplayAs={displayAs}
>
<PlaceholderNoteBlock onClick={addNoteBlock} />
</Outline>
)
)}
{subentities.length || isChildren
? // <DragandDrop
// dndContext={tabContext.viewId}
// listId={data?.uid}
// arrayId={data?._value?.children?.uid}
// style={dropIndicatorStyles}
// transformOnDrop={(props: any) => {
// return {
// ...props,
// uid: undefined,
// data: {
// type: { 'unigraph.id': '$/schema/embed_block' },
// _value: {
// content: { uid: props.uid },
// },
// },
// };
// }}
// >
(subentities as PlainUnigraphObject[]).map((entity, index) => {
if (!entity?.uid) return undefined;
const { uid } = entity;
const isCollapsed = isChildrenCollapsed[uid];
return (
<Outline
key={uid}
object={entity}
parentObject={data}
index={index}
editorContext={editorContext}
collapsed={isCollapsed}
setCollapsed={(val: boolean) => {
setIsChildrenCollapsed({
...isChildrenCollapsed,
[uid]: val,
});
}}
// createBelow={() => {
// addChild(data, editorContext, elindex);
// }}
displayAs={childrenDisplayAs}
parentDisplayAs={displayAs}
showCollapse={getSubentities(entity)[0].length >= 1}
>
<BlockChild
el={entity}
elindex={index}
editorContext={editorContext}
callbacks={getCallbacks(callbacks, data, editorContext, index)}
shortcuts={getShortcuts(data, editorContext, index, copyOrCutHandler, callbacks)}
isCollapsed={isCollapsed}
setCollapsed={(val: boolean) => {
setIsChildrenCollapsed({
...isChildrenCollapsed,
[uid]: val,
});
}}
displayAs={childrenDisplayAs}
/>
</Outline>
);
})
: // </DragandDrop>
data && (
<Outline
object={data}
index={0}
editorContext={editorContext}
displayAs={data?._value?.children?._displayAs || 'outliner'}
parentDisplayAs={displayAs}
>
<PlaceholderNoteBlock onClick={addNoteBlock} />
</Outline>
)}
</div>
);
};
Expand Down
80 changes: 69 additions & 11 deletions packages/unigraph-dev-explorer/src/examples/notes/Outline.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/* eslint-disable react/require-default-props */
import React from 'react';
import { useDrag } from 'react-dnd';
import { useDrag, useDrop } from 'react-dnd';
import { colors } from '@mui/material';
import { styled } from '@mui/styles';
import { ChevronRight } from '@mui/icons-material';

import { DragHandle } from './DragHandle';
import { DataContext, TabContext } from '../../utils';
import { UnigraphObject } from './types';
import { NoteEditorContext, UnigraphObject } from './types';

const OutlineContainer = styled('div')({
flex: '0 0 auto',
Expand Down Expand Up @@ -68,10 +68,37 @@ const ChildrenContainer = styled('div')({
wordBreak: 'break-word',
});

const DropTargetAfter = styled('div')({
position: 'absolute',
left: '2rem',
right: 0,
bottom: -10,
height: 20,
});

const DropIndicator = styled('div')({
position: 'absolute',
left: '2rem',
right: 0,
bottom: -2,
height: 4,
zIndex: -1,
});

/** Describe the object being dragged. */
interface DragObject {
uid: string;
parentUid: string;
itemType: string | undefined;
tabId: number;
}

interface OutlineProps {
object: UnigraphObject;
parentObject?: UnigraphObject;
/** The index within its siblings. */
index: number;
editorContext?: NoteEditorContext;
children?: React.ReactNode;
collapsed?: boolean;
setCollapsed?: (val: boolean) => void;
Expand All @@ -88,7 +115,9 @@ export const OutlineContentContext = React.createContext<React.MutableRefObject<
/** A container for both the content and its children. */
export function Outline({
object,
parentObject,
index,
editorContext,
children,
collapsed,
setCollapsed,
Expand All @@ -109,18 +138,16 @@ export function Outline({

const dataContext = React.useContext(DataContext);
const tabContext = React.useContext(TabContext);
const deleteOutline = React.useCallback(() => {
console.log('removeFromContext', object);
}, [object]);
const [, setDragSource] = useDrag(
const dndType = 'outliner-dnd';

const [, setDragSource] = useDrag<DragObject, unknown, unknown>(
() => ({
type: object.type?.['unigraph.id'] || '$/schema/any',
type: dndType,
item: {
uid: object.uid,
parentUid: dataContext.contextUid,
itemType: object.type?.['unigraph.id'],
dndContext: tabContext.viewId,
dataContext: dataContext.contextUid,
removeFromContext: deleteOutline,
tabId: tabContext.viewId,
},
collect: (monitor) => {
if (monitor.isDragging() && window.dragselect) {
Expand All @@ -130,11 +157,36 @@ export function Outline({
isDragging: !!monitor.isDragging(),
};
},
end: (item, monitor) => console.log('end drag', monitor.getDropResult()),
}),
[object?.type?.['unigraph.id'], object?.uid, tabContext.viewId, dataContext.contextUid],
);

const [{ shouldShowDropTargetAfter }, setDropTarget] = useDrop<
DragObject,
unknown,
{ shouldShowDropTargetAfter: boolean }
>(
() => ({
accept: [dndType],
drop: (item) => {
console.log('drop', item.uid, 'to', parentObject?.uid, 'after index', index);
window.unigraph.runExecutable('$/executable/delete-item-from-list', {
where: item.parentUid,
item: item.uid,
});
window.unigraph.runExecutable('$/executable/add-item-to-list', {
where: parentObject?.uid,
item: item.uid,
indexes: [index],
});
},
collect: (monitor) => ({
shouldShowDropTargetAfter: !!monitor.isOver(),
}),
}),
[object.uid],
);

return (
<OutlineContainer
onPointerMove={onPointerMove}
Expand Down Expand Up @@ -177,6 +229,12 @@ export function Outline({
<ChildrenContainer>
<OutlineContentContext.Provider value={rContentEl}>{children}</OutlineContentContext.Provider>
</ChildrenContainer>
<DropIndicator
style={{
background: shouldShowDropTargetAfter ? 'rgba(63, 167, 223, 0.3)' : 'transparent',
}}
/>
<DropTargetAfter ref={setDropTarget} />
</OutlineContainer>
);
}

0 comments on commit aa75365

Please sign in to comment.