ui-layout-manager-dev 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +3 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/Worker/LayoutWorker.js +25 -14
- package/dist/esm/index.js +3 -3
- package/dist/esm/index.js.map +1 -1
- package/package.json +3 -2
- package/src/components/LayoutManager/Components/HandleBar/HandleBar.jsx +22 -3
- package/src/components/LayoutManager/Components/RootContainer/RootContainer.jsx +71 -14
- package/src/components/LayoutManager/Components/RootContainer/RootContainer.scss +6 -0
- package/src/components/LayoutManager/Controller/Worker/HandleRulesEnforcer.js +23 -12
- package/src/components/LayoutManager/Controller/Worker/LayoutEditor.js +2 -2
- package/src/components/LayoutManager/LayoutManager.jsx +9 -5
- package/src/components/LayoutManager/Providers/DragProvider.js +87 -0
- package/src/stories/LayoutManager.stories.js +14 -2
- package/src/stories/layouts/vsCode/default.json +2 -20
- package/src/stories/layouts/vsCode/sample1.json +5 -1
- package/src/stories/layouts/vsCode/workbench.json +144 -0
- package/src/stories/sample_components/fileeditor/FileEditor.jsx +48 -0
- package/src/stories/sample_components/fileeditor/workspace_sample.json +1 -0
- package/src/stories/sample_components/filetree/FileTree.jsx +26 -0
- package/src/stories/sample_components/filetree/workspace_sample.json +1 -0
- package/src/stories/sample_components/map/MapSample.jsx +1 -1
- package/src/stories/sample_components/editor/EditorVSCode.jsx +0 -11
- package/src/stories/sample_components/editor/filetree.json +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ui-layout-manager-dev",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "A react component to manage layout and themes in single page applications.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
"react-dom": "^18.2.0"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
+
"@dnd-kit/core": "^6.3.1",
|
|
65
66
|
"leaflet": "^1.9.4",
|
|
66
|
-
"sample-ui-component-library": "^0.0.
|
|
67
|
+
"sample-ui-component-library": "^0.0.16-dev"
|
|
67
68
|
}
|
|
68
69
|
}
|
|
@@ -22,6 +22,10 @@ export const HandleBar = ({orientation, parent, sibling1, sibling2}) => {
|
|
|
22
22
|
* It does the following:
|
|
23
23
|
* - Determines the dynamic prop being modified (width or height)
|
|
24
24
|
* - Determines the mouse down property to track (clientY or clientX)
|
|
25
|
+
* - Gets the references to the sibling elements
|
|
26
|
+
* - Gets the sibling sizes from the layout
|
|
27
|
+
* - Gets the sibling sizes from the layout reference
|
|
28
|
+
* - Saves the information in drag start info ref for access
|
|
25
29
|
* @param {MouseEvent} e
|
|
26
30
|
*/
|
|
27
31
|
const handleMouseDown = (e) => {
|
|
@@ -110,7 +114,7 @@ export const HandleBar = ({orientation, parent, sibling1, sibling2}) => {
|
|
|
110
114
|
sibling1: sibling1,
|
|
111
115
|
sibling2: sibling2
|
|
112
116
|
});
|
|
113
|
-
},
|
|
117
|
+
}, 4);
|
|
114
118
|
|
|
115
119
|
// Don't update container sizes we are past min or max values.
|
|
116
120
|
const sibling1SizeKeys = Object.keys(startInfo.sibling1LayoutConfig);
|
|
@@ -154,10 +158,25 @@ export const HandleBar = ({orientation, parent, sibling1, sibling2}) => {
|
|
|
154
158
|
e.stopPropagation();
|
|
155
159
|
document.removeEventListener("mousemove", handleMouseMove);
|
|
156
160
|
document.removeEventListener("mouseup", handleMouseUp);
|
|
157
|
-
|
|
158
|
-
dragStartInfo.current
|
|
161
|
+
clearTimeout(timerRef.current);
|
|
162
|
+
if (handleRef.current && dragStartInfo.current) {
|
|
163
|
+
handleRef.current.classList.remove(dragStartInfo.current.hoverClass);
|
|
164
|
+
}
|
|
165
|
+
dragStartInfo.current = null;
|
|
159
166
|
}
|
|
160
167
|
|
|
168
|
+
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
return () => {
|
|
171
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
172
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
173
|
+
if (timerRef.current) {
|
|
174
|
+
clearTimeout(timerRef.current);
|
|
175
|
+
timerRef.current = null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}, []);
|
|
179
|
+
|
|
161
180
|
return (
|
|
162
181
|
<React.Fragment >
|
|
163
182
|
{
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import React, { useEffect, useLayoutEffect, useState, useRef, useCallback, useContext } from "react";
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { Container } from "../Container/Container";
|
|
4
|
+
import { HandleBar } from "../HandleBar/HandleBar";
|
|
4
5
|
import { useLayoutController } from "../../Providers/LayoutProvider";
|
|
6
|
+
import {
|
|
7
|
+
DndContext,
|
|
8
|
+
PointerSensor,
|
|
9
|
+
useSensor,
|
|
10
|
+
useSensors
|
|
11
|
+
} from "@dnd-kit/core";
|
|
12
|
+
|
|
13
|
+
import { useDragState } from "../../Providers/DragProvider";
|
|
5
14
|
|
|
6
15
|
import "./RootContainer.scss"
|
|
16
|
+
|
|
17
|
+
|
|
7
18
|
/**
|
|
8
19
|
* Root node for the layout tree. This component will start
|
|
9
20
|
* rendering the tree and it will also watch for changes in the
|
|
@@ -14,21 +25,23 @@ import "./RootContainer.scss"
|
|
|
14
25
|
export const RootContainer = () => {
|
|
15
26
|
const controller = useLayoutController();
|
|
16
27
|
|
|
28
|
+
const { dragState, handleDragStart, handleDragOver, clearDrag } = useDragState();
|
|
29
|
+
|
|
17
30
|
const rootRef = useRef(null);
|
|
18
31
|
const timerRef = useRef(null);
|
|
19
32
|
const resizingRef = useRef(false);
|
|
20
|
-
|
|
33
|
+
|
|
21
34
|
// Create the container API that will be used by the controller.
|
|
22
35
|
const rootContainerAPI = useRef({});
|
|
23
36
|
rootContainerAPI.current = {};
|
|
24
37
|
|
|
25
38
|
const [childElements, setChildElements] = useState(null);
|
|
26
|
-
|
|
39
|
+
|
|
27
40
|
/**
|
|
28
41
|
* Renders child containers recursively.
|
|
29
42
|
*/
|
|
30
43
|
const processContainer = useCallback((node) => {
|
|
31
|
-
const childElements = [];
|
|
44
|
+
const childElements = [];
|
|
32
45
|
for (let index = 0; index < node.children.length; index++) {
|
|
33
46
|
const childNode = node.children[index];
|
|
34
47
|
|
|
@@ -36,31 +49,43 @@ export const RootContainer = () => {
|
|
|
36
49
|
const child = controller.ldf.containers[node.children[index].containerId];
|
|
37
50
|
child.parent = node;
|
|
38
51
|
childElements.push(
|
|
39
|
-
<Container key={index} meta={node.children[index]} id={child.id} node={child}/>
|
|
52
|
+
<Container key={index} meta={node.children[index]} id={child.id} node={child} />
|
|
40
53
|
);
|
|
41
54
|
} else if (childNode.type === "handleBar") {
|
|
42
55
|
if (node.orientation === "horizontal") {
|
|
43
56
|
childElements.push(
|
|
44
|
-
<
|
|
57
|
+
<HandleBar
|
|
58
|
+
key={index}
|
|
59
|
+
orientation="vertical"
|
|
60
|
+
parent={node.id}
|
|
61
|
+
sibling1={childNode.sibling1}
|
|
62
|
+
sibling2={childNode.sibling2}
|
|
63
|
+
/>
|
|
45
64
|
);
|
|
46
65
|
} else if (node.orientation === "vertical") {
|
|
47
66
|
childElements.push(
|
|
48
|
-
<
|
|
67
|
+
<HandleBar
|
|
68
|
+
key={index}
|
|
69
|
+
orientation="horizontal"
|
|
70
|
+
parent={node.id}
|
|
71
|
+
sibling1={childNode.sibling1}
|
|
72
|
+
sibling2={childNode.sibling2}
|
|
73
|
+
/>
|
|
49
74
|
);
|
|
50
75
|
}
|
|
51
76
|
}
|
|
52
77
|
};
|
|
53
78
|
return childElements;
|
|
54
|
-
},[controller]);
|
|
79
|
+
}, [controller]);
|
|
55
80
|
|
|
56
81
|
|
|
57
82
|
useLayoutEffect(() => {
|
|
58
|
-
if (controller) {
|
|
83
|
+
if (controller) {
|
|
59
84
|
const rootNode = controller.ldf.containers[controller.ldf.layoutRoot];
|
|
60
85
|
const hasChildren = rootNode.children && rootNode.children.length > 0
|
|
61
86
|
controller.registerContainer(rootNode.id, rootContainerAPI, rootRef.current);
|
|
62
87
|
|
|
63
|
-
if (hasChildren) {
|
|
88
|
+
if (hasChildren) {
|
|
64
89
|
if (rootNode.orientation === "horizontal") {
|
|
65
90
|
rootRef.current.style.flexDirection = "row";
|
|
66
91
|
} else if (rootNode.orientation === "vertical") {
|
|
@@ -68,7 +93,7 @@ export const RootContainer = () => {
|
|
|
68
93
|
}
|
|
69
94
|
}
|
|
70
95
|
|
|
71
|
-
setChildElements(hasChildren?processContainer(rootNode):null);
|
|
96
|
+
setChildElements(hasChildren ? processContainer(rootNode) : null);
|
|
72
97
|
|
|
73
98
|
// Create resize observer to monitor changes in the root container size.
|
|
74
99
|
const observer = new ResizeObserver((entries) => {
|
|
@@ -96,11 +121,43 @@ export const RootContainer = () => {
|
|
|
96
121
|
}
|
|
97
122
|
}, [controller]);
|
|
98
123
|
|
|
124
|
+
const sensors = useSensors(
|
|
125
|
+
useSensor(PointerSensor, {
|
|
126
|
+
activationConstraint: {
|
|
127
|
+
distance: 8
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Manually track the drag position for smooth overlay
|
|
133
|
+
const [dragPos, setDragPos] = useState({ left: 0, top: 0 });
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
if (!dragState.isDragging) return;
|
|
136
|
+
const handleMove = (e) => {setDragPos({ left: e.clientX, top: e.clientY })};
|
|
137
|
+
window.addEventListener("pointermove", handleMove);
|
|
138
|
+
return () => {
|
|
139
|
+
window.removeEventListener("pointermove", handleMove);
|
|
140
|
+
};
|
|
141
|
+
}, [dragState.isDragging]);
|
|
142
|
+
|
|
99
143
|
return (
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
144
|
+
<DndContext sensors={sensors}
|
|
145
|
+
onDragStart={handleDragStart}
|
|
146
|
+
onDragOver={handleDragOver}
|
|
147
|
+
onDragEnd={clearDrag}
|
|
148
|
+
onDragCancel={clearDrag}>
|
|
149
|
+
|
|
150
|
+
<div className="root-container">
|
|
151
|
+
<div ref={rootRef} className="relative-container">
|
|
152
|
+
{childElements}
|
|
153
|
+
</div>
|
|
103
154
|
</div>
|
|
104
|
-
|
|
155
|
+
|
|
156
|
+
{dragState.isDragging && (
|
|
157
|
+
<div className="drag-overlay" style={dragPos}>
|
|
158
|
+
{dragState?.activeData?.preview}
|
|
159
|
+
</div>
|
|
160
|
+
)}
|
|
161
|
+
</DndContext>
|
|
105
162
|
);
|
|
106
163
|
}
|
|
@@ -11,6 +11,9 @@ import TRANSFORMATION_TYPES from "../TRANSFORMATION_TYPES";
|
|
|
11
11
|
* So rather than fully collapsing the container, it sets up a
|
|
12
12
|
* minimum size, this willl be useful for accordians and other containers.
|
|
13
13
|
*/
|
|
14
|
+
|
|
15
|
+
const COLLAPSE_THRESHOLD_PX = 50
|
|
16
|
+
|
|
14
17
|
export class HandleRulesEnforcer {
|
|
15
18
|
/**
|
|
16
19
|
* Initialize the child rule enforcer.
|
|
@@ -69,11 +72,13 @@ export class HandleRulesEnforcer {
|
|
|
69
72
|
return;
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
|
|
75
|
+
// Hide and unhide containers from left of container.
|
|
76
|
+
if (this.handleMetadata.handle.x < COLLAPSE_THRESHOLD_PX) {
|
|
77
|
+
// Handle is less than collapse threshold from the left
|
|
73
78
|
this.args = {style: {"display":"none", "min-width":0}}
|
|
74
79
|
this.sibling1.hidden = true;
|
|
75
80
|
this.activeSibling = this.sibling1.id;
|
|
76
|
-
} else if (this.handleMetadata.handle.x >
|
|
81
|
+
} else if (this.handleMetadata.handle.x > COLLAPSE_THRESHOLD_PX && this.sibling1.hidden) {
|
|
77
82
|
this.args = {style: {"display":"flex"}}
|
|
78
83
|
const sibling = this.getSiblingProps(this.sibling1.id);
|
|
79
84
|
if ("min" in sibling.size) {
|
|
@@ -81,14 +86,15 @@ export class HandleRulesEnforcer {
|
|
|
81
86
|
}
|
|
82
87
|
this.sibling1.hidden = false;
|
|
83
88
|
this.activeSibling = this.sibling1.id;
|
|
84
|
-
}
|
|
85
|
-
|
|
89
|
+
}
|
|
86
90
|
|
|
87
|
-
|
|
91
|
+
// Hide and unhide containrs from right of container.
|
|
92
|
+
if (this.handleMetadata.handle.x > totalWidth - COLLAPSE_THRESHOLD_PX) {
|
|
93
|
+
// Handle is greater than collapse threshold from right, so unhide container if it is hidden.
|
|
88
94
|
this.args = {style: {"display":"none", "min-width":0}}
|
|
89
95
|
this.sibling2.hidden = true;
|
|
90
96
|
this.activeSibling = this.sibling2.id;
|
|
91
|
-
} else if (this.handleMetadata.handle.x < totalWidth -
|
|
97
|
+
} else if (this.handleMetadata.handle.x < totalWidth - COLLAPSE_THRESHOLD_PX && this.sibling2.hidden) {
|
|
92
98
|
this.args = {style: {"display":"flex"}}
|
|
93
99
|
const sibling = this.getSiblingProps(this.sibling2.id);
|
|
94
100
|
if ("min" in sibling.size) {
|
|
@@ -101,7 +107,7 @@ export class HandleRulesEnforcer {
|
|
|
101
107
|
|
|
102
108
|
|
|
103
109
|
/**
|
|
104
|
-
* Process the
|
|
110
|
+
* Process the horizontal containers.
|
|
105
111
|
*/
|
|
106
112
|
processHorizontalContainers () {
|
|
107
113
|
const totalHeight = this.handleMetadata.sizes[this.parent.id].height;
|
|
@@ -113,11 +119,14 @@ export class HandleRulesEnforcer {
|
|
|
113
119
|
return;
|
|
114
120
|
}
|
|
115
121
|
|
|
116
|
-
|
|
122
|
+
// Hide and unhide containers from top of container.
|
|
123
|
+
if (this.handleMetadata.handle.y < COLLAPSE_THRESHOLD_PX) {
|
|
124
|
+
// Handle is less than collapse threshold from the top
|
|
117
125
|
this.args = {style: {"display":"none", "min-height":0}}
|
|
118
126
|
this.sibling1.hidden = true;
|
|
119
127
|
this.activeSibling = this.sibling1.id;
|
|
120
|
-
} else if (this.handleMetadata.handle.y >
|
|
128
|
+
} else if (this.handleMetadata.handle.y > COLLAPSE_THRESHOLD_PX && this.sibling1.hidden) {
|
|
129
|
+
// Handle is greater than collapse threshold from top, so unhide container if it is hidden.
|
|
121
130
|
this.args = {style: {"display":"flex"}}
|
|
122
131
|
const sibling = this.getSiblingProps(this.sibling1.id);
|
|
123
132
|
if ("min" in sibling.size) {
|
|
@@ -127,12 +136,14 @@ export class HandleRulesEnforcer {
|
|
|
127
136
|
this.activeSibling = this.sibling1.id;
|
|
128
137
|
}
|
|
129
138
|
|
|
130
|
-
|
|
131
|
-
if (this.handleMetadata.handle.y > totalHeight -
|
|
139
|
+
// Hide and unhide containrs from bottom of container.
|
|
140
|
+
if (this.handleMetadata.handle.y > totalHeight - COLLAPSE_THRESHOLD_PX) {
|
|
141
|
+
// Handle is less than collapse threshold from the bottom
|
|
132
142
|
this.args = {style: {"display":"none", "min-height":0}}
|
|
133
143
|
this.sibling2.hidden = true;
|
|
134
144
|
this.activeSibling = this.sibling2.id;
|
|
135
|
-
} else if (this.handleMetadata.handle.y < totalHeight -
|
|
145
|
+
} else if (this.handleMetadata.handle.y < totalHeight - COLLAPSE_THRESHOLD_PX && this.sibling2.hidden) {
|
|
146
|
+
// Handle is greater than collapse threshold from bottom, so unhide container if it is hidden.
|
|
136
147
|
this.args = {style: {"display":"flex"}}
|
|
137
148
|
const sibling = this.getSiblingProps(this.sibling2.id);
|
|
138
149
|
if ("min" in sibling.size) {
|
|
@@ -75,7 +75,7 @@ export class LayoutEditor {
|
|
|
75
75
|
childStyle["flex"] = "0 0 auto";
|
|
76
76
|
break;
|
|
77
77
|
case "fill":
|
|
78
|
-
childStyle["
|
|
78
|
+
childStyle["flex-grow"] = 1;
|
|
79
79
|
break;
|
|
80
80
|
default:
|
|
81
81
|
throw new Error(`Unknown size type "${child.size.initial.type}" in LDF configuration`);
|
|
@@ -154,7 +154,7 @@ export class LayoutEditor {
|
|
|
154
154
|
const parent = this.ldf.containers[containerId];
|
|
155
155
|
|
|
156
156
|
// If node is not split, then it has no children and is a leaf node, so we return.
|
|
157
|
-
if (
|
|
157
|
+
if (parent.type !== "split" || !("children" in parent)) {
|
|
158
158
|
return;
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import { RootContainer } from "./Components/RootContainer/RootContainer";
|
|
4
4
|
import ComponentRegistryContext from "./Providers/ComponentRegistryContext";
|
|
5
5
|
import { LayoutControllerProvider } from "./Providers/LayoutProvider";
|
|
6
|
+
import { DragProvider } from "./Providers/DragProvider";
|
|
6
7
|
|
|
7
8
|
import "./LayoutManager.scss";
|
|
8
9
|
|
|
@@ -15,13 +16,16 @@ import "./LayoutManager.scss";
|
|
|
15
16
|
* @return {React.ReactElement}
|
|
16
17
|
*/
|
|
17
18
|
export const LayoutManager = ({ldf, registry}) => {
|
|
19
|
+
|
|
18
20
|
|
|
19
21
|
return (
|
|
20
|
-
<
|
|
21
|
-
<
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
<DragProvider>
|
|
23
|
+
<LayoutControllerProvider layout={ldf}>
|
|
24
|
+
<ComponentRegistryContext.Provider value={registry}>
|
|
25
|
+
<RootContainer/>
|
|
26
|
+
</ComponentRegistryContext.Provider>
|
|
27
|
+
</LayoutControllerProvider>
|
|
28
|
+
</DragProvider>
|
|
25
29
|
);
|
|
26
30
|
}
|
|
27
31
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React, { createContext, useState, useCallback, useMemo } from "react";
|
|
2
|
+
|
|
3
|
+
const DragContext = createContext(null);
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Exposes the drag state through a hook. The state is updated
|
|
8
|
+
* by linking the drage events to dnd kit. The consuming appplication
|
|
9
|
+
* uses the hook and access the latest state. This will enable the
|
|
10
|
+
* consumer to react to drag start and over to preview interactions.
|
|
11
|
+
*
|
|
12
|
+
* TODO:
|
|
13
|
+
* In the initial implementation, the child components will use the
|
|
14
|
+
* useDrag hook and react to the state change on drop. However,
|
|
15
|
+
* eventually, I will modify it so that I only trigger the drop
|
|
16
|
+
* on the component in which it was dropped. For now, all the components
|
|
17
|
+
* will check to see if the drop was for them and ignore it if it isn't.
|
|
18
|
+
*/
|
|
19
|
+
export const DragProvider = ({ children }) => {
|
|
20
|
+
|
|
21
|
+
const [dragState, setDragState] = useState({
|
|
22
|
+
activeId: null,
|
|
23
|
+
activeData: null,
|
|
24
|
+
overId: null,
|
|
25
|
+
overData: null,
|
|
26
|
+
isDragging: false
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
const [drop, setDrop] = useState(null);
|
|
31
|
+
|
|
32
|
+
const handleDragStart = useCallback((event) => {
|
|
33
|
+
setDragState({
|
|
34
|
+
activeId: event.active?.id ?? null,
|
|
35
|
+
activeData: event.active?.data?.current ?? null,
|
|
36
|
+
overId: null,
|
|
37
|
+
overData: null,
|
|
38
|
+
isDragging: true
|
|
39
|
+
});
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
const handleDragOver = useCallback((event) => {
|
|
43
|
+
setDragState((prev) => ({
|
|
44
|
+
...prev,
|
|
45
|
+
overId: event.over?.id ?? null,
|
|
46
|
+
overData: event.over?.data?.current ?? null,
|
|
47
|
+
}));
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
const clearDrag = useCallback((event) => {
|
|
51
|
+
setDrop({
|
|
52
|
+
activeId: event.active?.id ?? null,
|
|
53
|
+
activeData: event.active?.data?.current ?? null,
|
|
54
|
+
overId: event.over?.id ?? null,
|
|
55
|
+
overData: event.over?.data?.current ?? null,
|
|
56
|
+
});
|
|
57
|
+
setDragState({
|
|
58
|
+
activeId: null,
|
|
59
|
+
activeData: null,
|
|
60
|
+
overId: null,
|
|
61
|
+
overData: null,
|
|
62
|
+
isDragging: false,
|
|
63
|
+
});
|
|
64
|
+
}, []);
|
|
65
|
+
|
|
66
|
+
const value = useMemo(() => ({
|
|
67
|
+
dragState,
|
|
68
|
+
drop,
|
|
69
|
+
handleDragStart,
|
|
70
|
+
handleDragOver,
|
|
71
|
+
clearDrag,
|
|
72
|
+
}), [dragState, drop, handleDragStart, handleDragOver, clearDrag]);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<DragContext.Provider value={value}>
|
|
76
|
+
{children}
|
|
77
|
+
</DragContext.Provider>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const useDragState = () => {
|
|
82
|
+
const ctx = React.useContext(DragContext);
|
|
83
|
+
if (!ctx) {
|
|
84
|
+
throw new Error("useDragState must be used inside DragProvider");
|
|
85
|
+
}
|
|
86
|
+
return ctx;
|
|
87
|
+
}
|
|
@@ -3,6 +3,7 @@ import { useArgs } from "@storybook/preview-api";
|
|
|
3
3
|
import { LayoutManager } from "../components/LayoutManager";
|
|
4
4
|
import defaultLayoutJSON from "./layouts/vsCode/default.json";
|
|
5
5
|
import sample1JSON from "./layouts/vsCode/sample1.json";
|
|
6
|
+
import workbenchJSON from "./layouts/vsCode/workbench.json";
|
|
6
7
|
|
|
7
8
|
import "./LayoutManager.stories.scss";
|
|
8
9
|
|
|
@@ -20,8 +21,8 @@ const Template = (args) => {
|
|
|
20
21
|
const [, updateArgs] = useArgs();
|
|
21
22
|
|
|
22
23
|
const registry = useMemo(() => ({
|
|
23
|
-
|
|
24
|
-
import('./sample_components/
|
|
24
|
+
FileEditor: () =>
|
|
25
|
+
import('./sample_components/fileeditor/FileEditor').then((m) => ({
|
|
25
26
|
default: m.default,
|
|
26
27
|
})),
|
|
27
28
|
Stack: () =>
|
|
@@ -36,6 +37,10 @@ const Template = (args) => {
|
|
|
36
37
|
import('./sample_components/map/MapSample').then((m) => ({
|
|
37
38
|
default: m.default,
|
|
38
39
|
})),
|
|
40
|
+
FileTree: () =>
|
|
41
|
+
import('./sample_components/filetree/FileTree').then((m) => ({
|
|
42
|
+
default: m.default,
|
|
43
|
+
})),
|
|
39
44
|
}), []);
|
|
40
45
|
|
|
41
46
|
useEffect(() => {
|
|
@@ -62,3 +67,10 @@ sample1.args = {
|
|
|
62
67
|
ldf: sample1JSON
|
|
63
68
|
}
|
|
64
69
|
|
|
70
|
+
|
|
71
|
+
export const workbench = Template.bind({})
|
|
72
|
+
|
|
73
|
+
workbench.args = {
|
|
74
|
+
ldf: workbenchJSON
|
|
75
|
+
}
|
|
76
|
+
|
|
@@ -39,8 +39,7 @@
|
|
|
39
39
|
"containerId": "sidebar",
|
|
40
40
|
"type": "container",
|
|
41
41
|
"size": { "initial": { "value": 50, "unit": "px", "type": "fixed" }},
|
|
42
|
-
"collapse": { "value": 400, "condition": "lessThan", "relative": "parent" }
|
|
43
|
-
"showHandlebar": true
|
|
42
|
+
"collapse": { "value": 400, "condition": "lessThan", "relative": "parent" }
|
|
44
43
|
},
|
|
45
44
|
{
|
|
46
45
|
"containerId": "contentContainer",
|
|
@@ -165,24 +164,12 @@
|
|
|
165
164
|
"containerId": "stackContainer",
|
|
166
165
|
"type": "container",
|
|
167
166
|
"size": { "initial": { "type": "fill" }}
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
"type": "handleBar",
|
|
171
|
-
"sibling1": "stackContainer",
|
|
172
|
-
"sibling2": "stackContainer2"
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
"containerId": "stackContainer2",
|
|
176
|
-
"type": "container",
|
|
177
|
-
"size": {
|
|
178
|
-
"initial": { "value": 200, "unit": "px", "type": "fixed" }
|
|
179
|
-
},
|
|
180
|
-
"collapse": { "value": 500, "condition": "lessThan", "relative": "parent" }
|
|
181
167
|
}
|
|
182
168
|
]
|
|
183
169
|
},
|
|
184
170
|
"fileTabsContainer": {
|
|
185
171
|
"id": "fileTabsContainer",
|
|
172
|
+
"component": "FileBrowser",
|
|
186
173
|
"background": "#1e1e1e"
|
|
187
174
|
},
|
|
188
175
|
"stackContainer": {
|
|
@@ -190,11 +177,6 @@
|
|
|
190
177
|
"component": "Stack",
|
|
191
178
|
"background": "#1e1e1e"
|
|
192
179
|
},
|
|
193
|
-
"stackContainer2": {
|
|
194
|
-
"id": "stackContainer2",
|
|
195
|
-
"component": "Stack",
|
|
196
|
-
"background": "#1e1e1e"
|
|
197
|
-
},
|
|
198
180
|
"editorContainer": {
|
|
199
181
|
"id": "editorContainer",
|
|
200
182
|
"component": "EditorVSCode",
|
|
@@ -145,12 +145,16 @@
|
|
|
145
145
|
{
|
|
146
146
|
"containerId": "stackContainer2",
|
|
147
147
|
"type": "container",
|
|
148
|
-
"size": {
|
|
148
|
+
"size": {
|
|
149
|
+
"initial": { "value": 200, "unit": "px", "type": "fixed" }
|
|
150
|
+
},
|
|
151
|
+
"collapse": { "value": 500, "condition": "lessThan", "relative": "parent" }
|
|
149
152
|
}
|
|
150
153
|
]
|
|
151
154
|
},
|
|
152
155
|
"fileTabsContainer": {
|
|
153
156
|
"id": "fileTabsContainer",
|
|
157
|
+
"component": "FileBrowser",
|
|
154
158
|
"background": "#1e1e1e"
|
|
155
159
|
},
|
|
156
160
|
"stackContainer": {
|