ui-layout-manager-dev 0.0.21 → 0.0.23-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.21",
3
+ "version": "0.0.23-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",
@@ -134,9 +134,23 @@ export const HandleBar = ({orientation, parent, sibling1, sibling2}) => {
134
134
  if (newSibling1Size < MIN_PANEL_SIZE || newSibling2Size < MIN_PANEL_SIZE) {
135
135
  return;
136
136
  }
137
+
138
+ // If both siblings are type fill, then set sizes.
139
+ const sibling1Type = startInfo.sibling1LayoutConfig.initial.type;
140
+ const sibling2Type = startInfo.sibling2LayoutConfig.initial.type;
141
+ if (sibling1Type === "fill" && sibling2Type === "fill") {
142
+ controller.containerRefs[sibling1].style[startInfo.propKey] = newSibling1Size + "px";
143
+ controller.containerRefs[sibling2].style[startInfo.propKey] = newSibling2Size + "px";
144
+ return;
145
+ }
137
146
 
138
- controller.containerRefs[sibling1].style[startInfo.propKey] = newSibling1Size + "px";
139
- controller.containerRefs[sibling2].style[startInfo.propKey] = newSibling2Size + "px";
147
+ // Don't update fill type siblings, if one of the siblings isn't fill type.
148
+ if (!(sibling1Type === "fill")) {
149
+ controller.containerRefs[sibling1].style[startInfo.propKey] = newSibling1Size + "px";
150
+ }
151
+ if (!(sibling2Type === "fill")) {
152
+ controller.containerRefs[sibling2].style[startInfo.propKey] = newSibling2Size + "px";
153
+ }
140
154
  }
141
155
 
142
156
  /**
@@ -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
  }
@@ -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
 
@@ -19,13 +20,15 @@ export const LayoutManager = ({ldf, registry}) => {
19
20
 
20
21
 
21
22
  return (
22
- <LayoutControllerProvider layout={ldf}>
23
- <LayoutEventProvider>
24
- <ComponentRegistryContext.Provider value={registry}>
25
- <RootContainer/>
26
- </ComponentRegistryContext.Provider>
27
- </LayoutEventProvider>
28
- </LayoutControllerProvider>
23
+ <ModalProvider>
24
+ <LayoutControllerProvider layout={ldf}>
25
+ <LayoutEventProvider>
26
+ <ComponentRegistryContext.Provider value={registry}>
27
+ <RootContainer/>
28
+ </ComponentRegistryContext.Provider>
29
+ </LayoutEventProvider>
30
+ </LayoutControllerProvider>
31
+ </ModalProvider>
29
32
  );
30
33
  }
31
34
 
@@ -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";
@@ -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 (