react-modal-orchestrator 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # ModalLib
1
+ # react-modal-orchestrator
2
2
 
3
3
  A centralized and flexible modal management system for React applications, now with lazy loading!
4
4
 
@@ -14,7 +14,7 @@ A centralized and flexible modal management system for React applications, now w
14
14
  ## Installation
15
15
 
16
16
  ```bash
17
- npm install modallib
17
+ npm install react-modal-orchestrator
18
18
  ```
19
19
 
20
20
  ## Setup
package/package.json CHANGED
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "name": "react-modal-orchestrator",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "exports": {
10
+ ".": "./dist/index.js"
11
+ },
6
12
  "scripts": {
7
13
  "build": "tsc",
8
14
  "prepublishOnly": "npm run build",
@@ -1,9 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="JAVA_MODULE" version="4">
3
- <component name="NewModuleRootManager" inherit-compiler-output="true">
4
- <exclude-output />
5
- <content url="file://$MODULE_DIR$" />
6
- <orderEntry type="inheritedJdk" />
7
- <orderEntry type="sourceFolder" forTests="false" />
8
- </component>
9
- </module>
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="AgentMigrationStateService">
4
- <option name="migrationStatus" value="COMPLETED" />
5
- </component>
6
- </project>
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="AskMigrationStateService">
4
- <option name="migrationStatus" value="COMPLETED" />
5
- </component>
6
- </project>
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="Ask2AgentMigrationStateService">
4
- <option name="migrationStatus" value="COMPLETED" />
5
- </component>
6
- </project>
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="EditMigrationStateService">
4
- <option name="migrationStatus" value="COMPLETED" />
5
- </component>
6
- </project>
package/.idea/misc.xml DELETED
@@ -1,15 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="MaterialThemeProjectNewConfig">
4
- <option name="metadata">
5
- <MTProjectMetadataState>
6
- <option name="migrated" value="true" />
7
- <option name="pristineConfig" value="false" />
8
- <option name="userId" value="1f7785cf:191c2f026d3:-7ffe" />
9
- </MTProjectMetadataState>
10
- </option>
11
- </component>
12
- <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="temurin-17" project-jdk-type="JavaSDK">
13
- <output url="file://$PROJECT_DIR$/out" />
14
- </component>
15
- </project>
package/.idea/modules.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectModuleManager">
4
- <modules>
5
- <module fileurl="file://$PROJECT_DIR$/.idea/ModalLib.iml" filepath="$PROJECT_DIR$/.idea/ModalLib.iml" />
6
- </modules>
7
- </component>
8
- </project>
@@ -1,97 +0,0 @@
1
- # What to do when creating a modal.
2
-
3
- # 1. Create a new file named `MyModalComponent.tsx` in the component folder.
4
-
5
- code template:
6
-
7
- (do not pass: isOpen or setIsOpen args)
8
-
9
- - set the `ModalWindow` isOpen to true
10
- - use `closeModal` from `ModalContext` to close the modal
11
-
12
- ```javascript
13
- const ModalComponent = () => {
14
- const { closeModal } = useContext(ModalContext);
15
-
16
- return (
17
- <AEMPage pagePath={pagePath} aemHost={getAEMHost()}>
18
- <ModalWindow variant={"large"} isOpen={true} onClose={closeModal}>
19
- <ModalHeader onClose={closeModal}>
20
- <div className={styles.modalHeader}>
21
- MODAL HEADER
22
- </div>
23
- <button onClick={()=> closeModal()}>CLOSE</button>
24
- </ModalHeader>
25
- <ModalBody>
26
- <div>
27
- MODAL BODY
28
- </div>
29
- </ModalBody>
30
- <ModalFooter placement="right">
31
- <div>
32
- MODAL FOOTER
33
- </div>
34
- </ModalFooter>
35
- </ModalWindow>
36
- </AEMPage>
37
- );
38
- };
39
- export default ModalComponent;
40
- ```
41
-
42
- # 2. Add the new modal to the constant `modals` in `ModalDictionary.tsx`.
43
- # 3. Add a definition to the RenderingDictionary.
44
-
45
- When adding the new modal to `bootstrap` for local rendering
46
- - the aemComponent and/or localComponent should be the ModalHandler
47
- - the modal will be prefixed with an alias to the group, to specify which modal it is
48
-
49
- # 4. How to trigger your modal?
50
-
51
- - use the `openModal` method from `ModalContext` to trigger the modal; `openModal` takes the name of the modal as defined in the
52
- modalDictionary, optionally you can also pass in props to the modal when you are opening it.
53
-
54
- ```javascript
55
- const { openModal } = useContext(ModalContext);
56
-
57
- const handleClick = () => openModal("PST_MODAL", {
58
- data: "myDatal"
59
- });
60
- ```
61
-
62
- ## What if my modal needs data?
63
- It is not recommended to access state and/or functionality using the`useContext` hook from within your modal component (this includes accessing context from any custom hooks employed by the modal component). It is very likely that the provider supplying the context will not be available when the modal is rendered, leading to errors. Instead, you should use
64
- optional props of the `openModal` method, allowing your modal to receive data when it is rendered. The props will be accessible in the modal component through the `props` argument. The only `useContext` hook you should use in your modal component is the `ModalContext` to access the `closeModal` method.
65
-
66
- When passing optional props to the modal, you can access them in the modal component like this:
67
-
68
- ```javascript
69
- const ModalComponent = ({data}: {data:string}) => {
70
- console.log(data); // "myData" <<==== ACCESSING THE DATA PASSED TO THE MODAL
71
- const { closeModal } = useContext(ModalContext); // <<==== ONLY useContext hook useage. ACCESSING THE CLOSE MODAL FUNCTION
72
- const { data } = modalProps;
73
-
74
- return (
75
- <AEMPage pagePath={pagePath} aemHost={getAEMHost()}>
76
- <ModalWindow variant={"large"} isOpen={true} onClose={closeModal}>
77
- <ModalHeader onClose={closeModal}>
78
- <div className={styles.modalHeader}>
79
- MODAL HEADER
80
- </div>
81
- </ModalHeader>
82
- <ModalBody>
83
- <div>
84
- MODAL BODY with data: {data}
85
- </div>
86
- </ModalBody>
87
- <ModalFooter placement="right">
88
- <div>
89
- MODAL FOOTER
90
- </div>
91
- </ModalFooter>
92
- </ModalWindow>
93
- </AEMPage>
94
- );
95
- };
96
- export default ModalComponent;
97
- ```
@@ -1,17 +0,0 @@
1
- import { useContext, Suspense } from "react";
2
- import {ModalDispatchContext, ModalStateContext} from "../contexts/ModalContext";
3
-
4
- const ModalHandler = () => {
5
- const { modal, ModalComponent } = useContext(ModalStateContext);
6
- const { closeModal } = useContext(ModalDispatchContext);
7
-
8
- if (!modal || !ModalComponent) return null;
9
- if (modal) document.body.style.removeProperty("overflow");
10
-
11
- return (
12
- <Suspense fallback={<div>Loading...</div>}>
13
- <ModalComponent onClose={closeModal} {...modal.props} />
14
- </Suspense>
15
- );
16
- };
17
- export default ModalHandler;
@@ -1,33 +0,0 @@
1
- import { type ReactNode, useMemo } from "react";
2
- import {useModal} from "../hooks/useModal";
3
- import {type GenericObjectType} from "../types";
4
- import {ModalDispatchContext, ModalStateContext } from "../contexts/ModalContext";
5
-
6
- const ModalOrchestrator = ({
7
- modals,
8
- children,
9
- }: {
10
- modals: GenericObjectType;
11
- children: ReactNode;
12
- }) => {
13
- const { modal, ModalComponent, openModal, closeModal } = useModal(modals);
14
-
15
- const state = useMemo(
16
- () => ({ modal, ModalComponent }),
17
- [modal, ModalComponent],
18
- );
19
- const dispatch = useMemo(
20
- () => ({ openModal, closeModal }),
21
- [openModal, closeModal],
22
- );
23
-
24
- return (
25
- <ModalStateContext.Provider value={state}>
26
- <ModalDispatchContext.Provider value={dispatch}>
27
- {children}
28
- </ModalDispatchContext.Provider>
29
- </ModalStateContext.Provider>
30
- );
31
- };
32
-
33
- export default ModalOrchestrator;
@@ -1,14 +0,0 @@
1
- import { createContext } from "react";
2
- import { useModal } from "../hooks/useModal";
3
-
4
- type ModalContextType = ReturnType<typeof useModal>;
5
-
6
- // This context will hold the stateful values that cause re-renders.
7
- export const ModalStateContext = createContext<
8
- Pick<ModalContextType, "modal" | "ModalComponent">
9
- >(null!);
10
-
11
- // This context will hold the stable dispatch functions.
12
- export const ModalDispatchContext = createContext<
13
- Pick<ModalContextType, "openModal" | "closeModal">
14
- >(null!);
@@ -1,65 +0,0 @@
1
- import { type FC, useRef, useState } from "react";
2
- import { type GenericModal, type GenericObjectType } from "../types";
3
-
4
- /**
5
- * A custom hook to manage modals in a React application.
6
- * It allows opening and closing modals, and keeps track of the modal stack.
7
- *
8
- * @param {GenericObjectType} modals - An object containing modal components.
9
- * @returns {Object} - An object containing the current modal component, openModal and closeModal functions.
10
- */
11
-
12
- type UseModalReturnType = {
13
- ModalComponent: FC<any> | null;
14
- modal: GenericModal | null;
15
- openModal: (name: string, props?: object) => void;
16
- closeModal: () => void;
17
- };
18
- export const smallGreyFont = "color: grey; font-size: 85%";
19
- export const keyFont = "color: orange;font-weight: bold;";
20
-
21
- export const useModal = (modals: GenericObjectType): UseModalReturnType => {
22
- const modalStack = useRef<GenericModal[]>([]); // For purpose of keeping track of the modal stack, especially when there are multiple modals open
23
- const [modal, setModal] = useState<GenericModal | null>(null);
24
- const ModalLookup: GenericObjectType = { ...modals };
25
- const modalName = modal ? modal.name : "";
26
- const ModalComponent = ModalLookup[modalName];
27
-
28
- const openModal = (name: string, props = {}) => {
29
- // Check if the modal is already open
30
- const existingModal = modalStack.current.find(
31
- (modal: GenericModal) => modal.name === name,
32
- );
33
- if (existingModal) {
34
- // If the modal is already open, just update its props
35
- // additionally we don't need try/catch here, because we already know the modal name exists
36
- existingModal.props = { ...existingModal.props, ...props };
37
- setModal(existingModal);
38
- return;
39
- }
40
-
41
- try {
42
- if (name in ModalLookup) {
43
- modalStack.current.push({ name, props });
44
- setModal({ name, props });
45
- } else {
46
- console.log("%cModalManager %copening:", keyFont, smallGreyFont, name);
47
- console.log("%cModalStack", smallGreyFont, modalStack.current);
48
- throw new Error(
49
- `Modal with name "${name}" does not exist in ModalLookup.`,
50
- );
51
- }
52
- } catch (error) {
53
- console.log("Failed to open modal:", error);
54
- console.error("Failed to open modal:", error);
55
- }
56
- };
57
-
58
- const closeModal = () => {
59
- console.log("closeModal");
60
- modalStack.current.pop();
61
- setModal(modalStack.current[modalStack.current.length - 1] ?? null);
62
- };
63
-
64
- return { ModalComponent, modal, openModal, closeModal };
65
- };
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export { default as ModalOrchestrator } from './Modal/ModalOrchestrator';
2
- export { default as ModalHandler } from './Modal/ModalHandler';
3
- export { ModalDispatchContext, ModalStateContext } from './contexts/ModalContext';
package/src/types.ts DELETED
@@ -1,7 +0,0 @@
1
- export type GenericObjectType = {
2
- [key: string]: any;
3
- };
4
- export type GenericModal = {
5
- name: string;
6
- props?: Record<string, any>;
7
- };
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "declaration": true,
4
- "emitDeclarationOnly": true,
5
- "esModuleInterop": true,
6
- "forceConsistentCasingInFileNames": true,
7
- "isolatedModules": true,
8
- "jsx": "react-jsx",
9
- "lib": ["DOM", "ESNext"],
10
- "module": "CommonJS",
11
- "moduleResolution": "node",
12
- "noFallthroughCasesInSwitch": true,
13
- "outDir": "./dist",
14
- "strict": true,
15
- "target": "ESNext"
16
- }
17
- }