ui-layout-manager-dev 0.0.22 → 0.0.24-dev

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ui-layout-manager-dev",
3
- "version": "0.0.22",
3
+ "version": "0.0.24-dev",
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",
@@ -144,7 +144,7 @@ export const HandleBar = ({orientation, parent, sibling1, sibling2}) => {
144
144
  return;
145
145
  }
146
146
 
147
- // If one sibling is fill type but the other isn't, don't update, flex box will take care of that
147
+ // Don't update fill type siblings, if one of the siblings isn't fill type.
148
148
  if (!(sibling1Type === "fill")) {
149
149
  controller.containerRefs[sibling1].style[startInfo.propKey] = newSibling1Size + "px";
150
150
  }
@@ -46,6 +46,6 @@ export const Tabs = ({node, onTabClick}) => {
46
46
  }
47
47
 
48
48
  Tabs.propTypes = {
49
- node: PropTypes.array,
50
- onTabsClick: PropTypes.func
49
+ node: PropTypes.object,
50
+ onTabClick: PropTypes.func
51
51
  }
@@ -147,7 +147,7 @@ export const RootContainer = () => {
147
147
  onDragEnd={dragController.onDragEnd}
148
148
  onDragCancel={dragController.onDragCancel}>
149
149
 
150
- <div className="root-container">
150
+ <div id="layout-root" className="root-container">
151
151
  <div ref={rootRef} className="relative-container">
152
152
  {childElements}
153
153
  </div>
@@ -4,6 +4,7 @@ import { RootContainer } from "./Components/RootContainer/RootContainer";
4
4
  import ComponentRegistryContext from "./Providers/ComponentRegistryContext";
5
5
  import { LayoutControllerProvider } from "./Providers/LayoutProvider";
6
6
  import { LayoutEventProvider } from "./Providers/LayoutEventProvider";
7
+ import { ModalProvider } from "./Providers/ModalProvider";
7
8
 
8
9
  import "./LayoutManager.scss";
9
10
 
@@ -22,7 +23,9 @@ export const LayoutManager = ({ldf, registry}) => {
22
23
  <LayoutControllerProvider layout={ldf}>
23
24
  <LayoutEventProvider>
24
25
  <ComponentRegistryContext.Provider value={registry}>
25
- <RootContainer/>
26
+ <ModalProvider>
27
+ <RootContainer/>
28
+ </ModalProvider>
26
29
  </ComponentRegistryContext.Provider>
27
30
  </LayoutEventProvider>
28
31
  </LayoutControllerProvider>
@@ -0,0 +1,53 @@
1
+ .modal-backdrop {
2
+ position: fixed;
3
+ top: 0;
4
+ left: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ background-color: rgba(0, 0, 0, 0.5);
8
+ display: flex;
9
+ justify-content: center;
10
+ align-items: center;
11
+ z-index: 1000;
12
+ }
13
+
14
+ .modal-content {
15
+ background-color: #333333;
16
+ border-radius: 5px;
17
+ display: flex;
18
+ flex-direction: column;
19
+ max-width: 500px;
20
+ max-height: 500px;
21
+ scrollbar-gutter: stable;
22
+ scrollbar-color: #47474766 #252526;
23
+ scrollbar-width: thin;
24
+ }
25
+
26
+ .modal-header {
27
+ display:flex;
28
+ justify-content: space-between;
29
+ height:25px;
30
+ border-bottom: solid 1px rgb(85, 85, 85);
31
+ padding: 10px 20px;
32
+ align-items: center;
33
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
34
+ }
35
+
36
+ .modal-header > .title {
37
+ color:rgb(180, 180, 180);
38
+ }
39
+
40
+ .modal-header > .close-button {
41
+ cursor: pointer;
42
+ color:rgb(180, 180, 180);
43
+ }
44
+
45
+ .modal-header > .close-button:hover {
46
+ color:white;
47
+ }
48
+
49
+ .modal-body {
50
+ flex: 1;
51
+ overflow: auto;
52
+ padding:10px;
53
+ }
@@ -0,0 +1,96 @@
1
+ // @ts-nocheck
2
+ import React, {
3
+ createContext,
4
+ useCallback,
5
+ useContext,
6
+ useMemo,
7
+ useState,
8
+ } from "react";
9
+
10
+ import { createPortal } from "react-dom";
11
+
12
+ import {XLg} from "react-bootstrap-icons";
13
+
14
+ const ModalContext = createContext(null);
15
+
16
+ /**
17
+ * Modal provider component to manage modals in the application
18
+ * @returns {JSX} The modal provider component
19
+ */
20
+ export function ModalProvider({ children }) {
21
+ const [modal, setModal] = useState(null);
22
+
23
+ // Open a modal with the given content and title. Returns a function to close the modal.
24
+ const openModal = useCallback(( args ) => {
25
+ const close = () => {
26
+ setModal(null);
27
+ };
28
+
29
+ const id = `modal-${Date.now()}`;
30
+ setModal({
31
+ id: id,
32
+ title: args.title,
33
+ render: args.render,
34
+ close: close,
35
+ });
36
+
37
+ return { id, close };
38
+ }, []);
39
+
40
+ // Close the currently open modal
41
+ const closeModal = useCallback(() => {
42
+ setModal(null);
43
+ }, []);
44
+
45
+ // Render the modal portal
46
+ // TODO: Add support for different sizes
47
+ const getPortal = () => {
48
+ return createPortal(
49
+ <>
50
+ {modal && (
51
+ <React.Fragment key={modal.id}>
52
+ <div className="modal-backdrop" onClick={modal.close}>
53
+ <div className="modal-content" onClick={(e) => e.stopPropagation()}>
54
+ <div className="modal-header">
55
+ <span className="title">{modal.title}</span>
56
+ <XLg className="close-button" onClick={modal.close} />
57
+ </div>
58
+ <div className="modal-body">
59
+ {modal.render({ close: modal.close })}
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </React.Fragment>
64
+ )}
65
+ </>,
66
+ document.body,
67
+ );
68
+ };
69
+
70
+ const api = useMemo(
71
+ () => ({
72
+ openModal,
73
+ closeModal,
74
+ }),
75
+ [openModal, closeModal],
76
+ );
77
+
78
+ return (
79
+ <ModalContext.Provider value={api}>
80
+ {children}
81
+ {getPortal()}
82
+ </ModalContext.Provider>
83
+ );
84
+ }
85
+
86
+ /**
87
+ * Modal manager hook to access the modal API
88
+ * @return {Object} The modal manager API
89
+ */
90
+ export function useModalManager() {
91
+ const value = useContext(ModalContext);
92
+ if (!value) {
93
+ throw new Error("useModalManager must be used inside ModalProvider");
94
+ }
95
+ return value;
96
+ }
package/src/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./components/LayoutManager";
2
2
  export { useLayoutEventPublisher } from "./components/LayoutManager/Providers/LayoutEventProvider";
3
- export { useLayoutEventSubscription } from "./components/LayoutManager/Providers/LayoutEventProvider";
3
+ export { useLayoutEventSubscription } from "./components/LayoutManager/Providers/LayoutEventProvider";
4
+ export { useModalManager } from "./components/LayoutManager/Providers/ModalProvider";
@@ -10,7 +10,7 @@
10
10
  {
11
11
  "containerId": "header",
12
12
  "type": "container",
13
- "size": { "initial": { "value": 0, "unit": "px", "type": "fixed" }}
13
+ "size": { "initial": { "value": 25, "unit": "px", "type": "fixed" }}
14
14
  },
15
15
  {
16
16
  "containerId": "mainBody",
@@ -38,9 +38,8 @@
38
38
  {
39
39
  "containerId": "sidebar",
40
40
  "type": "container",
41
- "size": { "initial": { "value": 0, "unit": "px", "type": "fixed" }},
42
- "collapse": { "value": 400, "condition": "lessThan", "relative": "parent" },
43
- "showHandlebar": true
41
+ "size": { "initial": { "value": 50, "unit": "px", "type": "fixed" }},
42
+ "collapse": { "value": 400, "condition": "lessThan", "relative": "parent" }
44
43
  },
45
44
  {
46
45
  "containerId": "contentContainer",
@@ -80,13 +79,13 @@
80
79
  "id": "terminal",
81
80
  "tabsBar": {
82
81
  "tabs": [
83
- {
84
- "name": "Terminal",
85
- "component": "PtyTerminal"
86
- },
87
82
  {
88
83
  "name": "Flow",
89
84
  "component": "Flow"
85
+ },
86
+ {
87
+ "name": "FileTree",
88
+ "component": "FileTree"
90
89
  }
91
90
  ],
92
91
  "showClose": true,
@@ -104,9 +103,9 @@
104
103
  "containerId": "menuContainer",
105
104
  "type": "container",
106
105
  "size": {
107
- "initial": { "value": 270, "unit": "px", "type": "fixed" },
108
- "min": { "value": 170, "unit": "px"},
109
- "max": { "value": 320, "unit": "px"}
106
+ "initial": { "value": 250, "unit": "px", "type": "fixed" },
107
+ "min": { "value": 200, "unit": "px"},
108
+ "max": { "value": 400, "unit": "px"}
110
109
  },
111
110
  "collapse": { "value": 700, "condition": "lessThan", "relative": "parent" }
112
111
  },
@@ -119,31 +118,6 @@
119
118
  "containerId": "editorContainer",
120
119
  "type": "container",
121
120
  "size": { "initial": { "type": "fill" }}
122
- },
123
- {
124
- "type": "handleBar",
125
- "sibling1": "editorContainer",
126
- "sibling2": "designLayoutContainer"
127
- },
128
- {
129
- "containerId": "designLayoutContainer",
130
- "type": "container",
131
- "size": { "initial": { "type": "fill" }}
132
- },
133
- {
134
- "type": "handleBar",
135
- "sibling1": "designLayoutContainer",
136
- "sibling2": "rightMenuContainer"
137
- },
138
- {
139
- "containerId": "rightMenuContainer",
140
- "type": "container",
141
- "size": {
142
- "initial": { "value": 270, "unit": "px", "type": "fixed" },
143
- "min": { "value": 170, "unit": "px"},
144
- "max": { "value": 320, "unit": "px"}
145
- },
146
- "collapse": { "value": 700, "condition": "lessThan", "relative": "parent" }
147
121
  }
148
122
  ]
149
123
  },
@@ -164,139 +138,23 @@
164
138
  {
165
139
  "containerId": "fileTabsContainer",
166
140
  "type": "container",
167
- "size": {
168
- "initial": { "value": 350, "unit": "px", "type": "fixed" },
169
- "min": { "value": 51, "unit": "px"}
170
- },
171
- "collapse": { "value": 400, "condition": "lessThan", "relative": "parent" }
172
- },
173
- {
174
- "type": "handleBar",
175
- "sibling1": "fileTabsContainer",
176
- "sibling2": "leftMenuContainer2"
177
- },
178
- {
179
- "containerId": "leftMenuContainer2",
180
- "type": "container",
181
- "size": { "initial": { "type": "fill" }}
182
- }
183
- ]
184
- },
185
- "rightMenuContainer": {
186
- "id": "rightMenuContainer",
187
- "background": "#252526",
188
- "type": "split",
189
- "orientation": "vertical",
190
- "children": [
191
- {
192
- "containerId": "rightMenuContainer1",
193
- "type": "container",
194
- "size": {
195
- "initial": { "value": 200, "unit": "px", "type": "fixed" },
196
- "min": { "value": 51, "unit": "px"}
197
- },
198
- "collapse": { "value": 400, "condition": "lessThan", "relative": "parent" }
199
- },
200
- {
201
- "type": "handleBar",
202
- "sibling1": "rightMenuContainer1",
203
- "sibling2": "rightMenuContainer3"
204
- },
205
- {
206
- "containerId": "rightMenuContainer2",
207
- "type": "container",
208
141
  "size": { "initial": { "type": "fill" }}
209
- },
210
- {
211
- "type": "handleBar",
212
- "sibling1": "rightMenuContainer2",
213
- "sibling2": "rightMenuContainer3"
214
- },
215
- {
216
- "containerId": "rightMenuContainer3",
217
- "type": "container",
218
- "size": {
219
- "initial": { "value": 200, "unit": "px", "type": "fixed" },
220
- "min": { "value": 51, "unit": "px"}
221
- },
222
- "collapse": { "value": 500, "condition": "lessThan", "relative": "parent" }
223
142
  }
224
143
  ]
225
144
  },
226
145
  "fileTabsContainer": {
227
146
  "id": "fileTabsContainer",
228
- "component": "DesignMetadata",
147
+ "component": "FileTree",
229
148
  "menuBar": {
230
149
  "showClose": true,
231
150
  "closeContainerId": "menuContainer",
232
- "title": "File Browser"
151
+ "title": "EXPLORER"
233
152
  },
234
153
  "background": "#1e1e1e"
235
154
  },
236
155
  "editorContainer": {
237
156
  "id": "editorContainer",
238
- "component": "EditorContainer",
239
- "background": "#1e1e1e"
240
- },
241
- "FlowContainer": {
242
- "id": "FlowContainer",
243
- "component": "Flow",
244
- "background": "#1e1e1e"
245
- },
246
- "designLayoutContainer": {
247
- "id": "designLayoutContainer",
248
- "type": "split",
249
- "orientation": "horizontal",
250
- "children": [
251
- {
252
- "containerId": "toolbarContainer",
253
- "type": "container",
254
- "size": { "initial": { "value": 40, "unit": "px", "type": "fixed" }},
255
- "collapse": { "value": 100, "condition": "lessThan", "relative": "parent" }
256
- },
257
- {
258
- "containerId": "FlowContainer",
259
- "type": "container",
260
- "size": { "initial": { "type": "fill" }}
261
- }
262
- ],
263
- "background": "#1e1e1e"
264
- },
265
- "leftMenuContainer2": {
266
- "id": "leftMenuContainer2",
267
- "menuBar": {
268
- "showClose": false,
269
- "title": "File Browser3"
270
- },
271
- "background": "#1e1e1e"
272
- },
273
- "rightMenuContainer1": {
274
- "id": "rightMenuContainer1",
275
- "menuBar": {
276
- "showClose": false,
277
- "title": "Behaviors"
278
- },
279
- "background": "#1e1e1e"
280
- },
281
- "rightMenuContainer2": {
282
- "id": "rightMenuContainer2",
283
- "menuBar": {
284
- "showClose": false,
285
- "title": "Participants"
286
- },
287
- "background": "#1e1e1e"
288
- },
289
- "rightMenuContainer3": {
290
- "id": "rightMenuContainer3",
291
- "menuBar": {
292
- "showClose": false,
293
- "title": "Invariants"
294
- },
295
- "background": "#1e1e1e"
296
- },
297
- "toolbarContainer": {
298
- "id": "toolbarContainer",
299
- "component": "ToolBar",
157
+ "component": "FileEditor",
300
158
  "background": "#1e1e1e"
301
159
  }
302
160
  }
@@ -4,10 +4,13 @@ import { FileBrowser } from 'sample-ui-component-library';
4
4
  import tree from "./workspace_sample.json"
5
5
 
6
6
  import { useLayoutEventPublisher } from "../../../components/LayoutManager/Providers/LayoutEventProvider";
7
+ import { useModalManager } from "../../../components/LayoutManager/Providers/ModalProvider";
8
+ import Stack from "../stack/Stack";
7
9
 
8
10
  const FileTree = () => {
9
11
  const fileBrowserRef = useRef(null);
10
12
  const publish = useLayoutEventPublisher();
13
+ const { openModal } = useModalManager();
11
14
 
12
15
  useLayoutEffect(() => {
13
16
  fileBrowserRef.current.addFileTree(tree.tree);
@@ -21,7 +24,26 @@ const FileTree = () => {
21
24
  type: "file:selected",
22
25
  payload: node,
23
26
  source: "file-tree",
24
- })
27
+ });
28
+
29
+
30
+ // For demo purposes, if the readme file is selected, open a modal.
31
+ if (node.name === "readme") {
32
+ const {id, close} = openModal({
33
+ title:"Readme",
34
+ render: ({ close }) => {
35
+ return <>
36
+ <Stack />
37
+ <Stack />
38
+ </>;
39
+ }
40
+ });
41
+
42
+ // For demo purposes, automatically close the modal after 10 seconds.
43
+ // setTimeout(() => {
44
+ // close();
45
+ // }, 10000);
46
+ }
25
47
  }
26
48
 
27
49
  return (