Open
Description
I’m stuck with dragging text inside specific block that already is ReactSortable nested component. I did not find solution to render content inside nested ReactSortable component.
What I expect:
Dragging layout block ( example: 2 blocks ) into editor.
Dragging paragraph or heading into specific block (ex: in the first paragraph, in the second heading).
What I get:
- Dragging layout block appears in Editor.
- Dragging paragraph or heading doesn’t appear into specific block.
import { useState, createContext, useContext } from 'react';
import { ReactSortable } from 'react-sortablejs';
export const MyContext = createContext(null);
const orthographyInitState = [
{ id: 'p1', type: 'paragraph', content: <p>Paragraph</p> },
{ id: 'h1', type: 'heading', content: <h3>Heading</h3> },
];
const initialLayout2 = Array.from({ length: 2 }, (_, index) => ({
id: `l-2-${index + 1}`,
context: [],
width: ['30%', '70%'],
}));
const initialLayout6 = Array.from({ length: 6 }, (_, index) => ({
id: `l-2-${index + 1}`,
context: [],
}));
const Layout2 = () => {
const { editorState, setEditorState, layoutState, setLayoutState } = useContext(MyContext);
return (
<div style={{ display: 'flex' }}>
{initialLayout2?.map((layoutItem, idx) => (
<ReactSortable
key={layoutItem.id}
group={{
name: 'layout-item',
pull: true,
put: ['orthography-list', 'editor-list'],
}}
animation={150}
list={layoutItem.context}
setList={(currentChild) => {}}
style={{
border: '1px solid blue',
margin: 10,
minHeight: 50,
width: layoutItem?.width[idx],
}}
className="layout-container">
{layoutItem.context?.map((item, idx) => (
<div key={`${item.id}`} data-id={`${item.id}`} className="layout-content">
{item.content}
</div>
))}
</ReactSortable>
))}
</div>
);
};
const Layout6 = () => {
const initialLayout2 = Array.from({ length: 6 }, (_, index) => ({
id: `layout-6-${index + 1}`,
content: [],
}));
const [layoutState, setLayoutState] = useState(initialLayout2);
return (
<ReactSortable
list={layoutState}
setList={(newList) => setLayoutState(newList)}
group={{
name: 'layout-6',
pull: true,
put: [],
}}
animation={150}
style={{
border: '1px solid skyblue',
margin: 10,
minHeight: 50,
minWidth: 50,
display: 'flex',
flexDirection: 'row',
}}
className="layout-block">
{layoutState.map((sortable) => (
<ReactSortable
key={sortable.id}
data-id={sortable.id}
group={{
name: 'layout-item',
pull: true,
put: ['orthography-list', 'editor-list'],
}}
animation={150}
list={sortable.content}
setList={(newList) => {
const updatedState = layoutState.map((item) =>
item.id === sortable.id ? { ...item, content: [...item.content, ...newList] } : item,
);
console.log(`%c newList`, `color: #0af015`, newList);
setLayoutState(updatedState);
}}
style={{
border: '1px solid blue',
margin: 10,
minHeight: 50,
minWidth: 50,
}}
className="layout-container">
{sortable.content.map((item, idx) => {
console.log(`%c item`, `color: #0a9df0`, item);
return (
<div
key={`${item.id}-${idx}`}
data-id={`${item.id}-${idx}`}
className="layout-content">
{item.content}
</div>
);
})}
</ReactSortable>
))}
</ReactSortable>
);
};
const layoutInitialState = [
{
type: `layout-2`,
group: 'layout',
icon: '◼︎◼︎',
content: <Layout2 />,
child: initialLayout2,
},
{
type: 'layout-6',
group: 'layout',
icon: '◼︎◼︎◼︎◼︎◼︎◼︎',
content: <Layout6 />,
child: initialLayout6,
},
];
export const App = () => {
const [orthographyState, setOrthographyState] = useState(orthographyInitState);
const [layoutState, setLayoutState] = useState(layoutInitialState);
const [editorState, setEditorState] = useState([]);
const values = { orthographyState, layoutState, setLayoutState, editorState, setEditorState };
return (
<MyContext.Provider value={values}>
<div style={{ display: 'flex', flexDirection: 'row' }}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<Orthography />
<Layout />
</div>
<Editor />
</div>
</MyContext.Provider>
);
};
const Orthography = () => {
const { orthographyState } = useContext(MyContext);
return (
<ReactSortable
list={orthographyState}
setList={() => {}}
group={{
name: 'orthography-list',
pull: 'clone',
put: [],
}}
sort={false}
animation={150}
style={{ border: '1px solid red' }}
className="orthography-container">
{orthographyState.map((item, idx) => (
<div
key={`${item.id}-${idx}`}
data-id={`${item.id}-${idx}`}
className={`orthography-content`}>
{item.content}
</div>
))}
</ReactSortable>
);
};
const Layout = () => {
const { layoutState } = useContext(MyContext);
return (
<ReactSortable
list={layoutState}
setList={() => {}}
group={{
name: 'layout-list',
pull: 'clone',
put: [],
}}
sort={false}
animation={150}
style={{ border: '1px solid red' }}
className="layout-container">
{layoutState.map((item, idx) => (
<div key={`${item.id}-${idx}`} data-id={`${item.id}-${idx}`} className={`layout-content`}>
{item.icon}
</div>
))}
</ReactSortable>
);
};
const Editor = () => {
const { editorState, setEditorState, layoutState, setLayoutState } = useContext(MyContext);
return (
<ReactSortable
list={editorState}
setList={(currentState) => {
const updatedState = currentState.map((item, idx) => ({
...item,
id: `${item.type}-${idx}`,
}));
setEditorState(updatedState);
}}
group={{
name: 'editor-list',
pull: true,
put: ['layout-list', 'orthography-list', 'layout-item'],
}}
animation={150}
style={{ border: '1px solid green', minHeight: 200, minWidth: 600, margin: 10 }}
className="editor-container">
{editorState?.map((item, idx) => (
<div key={`${item.id}-${idx}`} data-id={`${item.id}-${idx}`} className="editor-content">
{item.content}
</div>
))}
</ReactSortable>
);
};
Metadata
Metadata
Assignees
Labels
No labels