Skip to content

Commit 56c035e

Browse files
committed
Modal props are now directly in the props instead of data, types are now more restrictive when using the component
1 parent 258ee98 commit 56c035e

5 files changed

Lines changed: 48 additions & 33 deletions

File tree

src/context.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
"use client";
2-
import { createContext, ReactNode, useContext, ReactElement } from "react";
1+
import { createContext, useContext } from "react";
2+
import { ModalItemProvider } from "./item-context";
33
import { ModalManager, ModalProviderProps } from "./types";
44
import { useModalManager } from "./use-modal-manager";
5-
import { ModalItemProvider } from "./item-context";
65

76
const ModalContext = createContext<ModalManager | null>(null);
87

@@ -39,7 +38,7 @@ function Modals({
3938
modal(modalInstance, modalManager)
4039
) : (
4140
<modalInstance.component
42-
data={modalInstance.data}
41+
{...modalInstance.props}
4342
close={modalInstance.close}
4443
isOpen={modalInstance.isOpen}
4544
id={modalInstance.id}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export { ModalProvider, useModals } from "./context";
2-
export { useModalManager } from "./use-modal-manager";
32
export { useBeforeClose } from "./item-context";
43
export type { ModalProps } from "./types";
4+
export { useModalManager } from "./use-modal-manager";

src/item-context.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
"use client";
21
import { createContext, useContext, useEffect } from "react";
32
import { ModalInstance } from "./types";
43

src/types.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,44 @@ export interface ModalProviderProps {
1212
modal?: (modal: ModalInstance, modals: ModalManager) => ReactElement;
1313
}
1414

15-
export interface ModalProps<ReturnValue = any> extends Record<string, any> {
15+
export interface ModalProps<ReturnValue = any> {
1616
index: number;
1717
id: string;
1818
isOpen: boolean;
1919
close: (value?: ReturnValue) => void;
2020
}
2121

22-
export interface ModalInstance<ReturnValue = any> {
23-
component: ComponentType<any>;
22+
// Type commun pour les composants modaux
23+
export type ModalComponent<T = any, ReturnValue = any> = ComponentType<
24+
ModalProps<ReturnValue> & T
25+
>;
26+
27+
export interface ModalInstance<T = any, ReturnValue = any> {
28+
component: ModalComponent<T, ReturnValue>;
2429
id: string;
25-
data?: any;
30+
props?: Omit<T, keyof ModalProps<ReturnValue>>;
2631
isOpen: boolean;
2732
close: (value?: ReturnValue) => void;
2833
index: number;
2934
onBeforeClose: (callback: () => boolean) => void;
3035
}
3136

3237
export interface ModalManager {
33-
open: <T = any, R = any>(
34-
component:
35-
| ComponentType<T>
36-
| (() => Promise<{ default: ComponentType<T> }>),
37-
data?: any,
38-
options?: ModalOptions
39-
) => Promise<R>;
38+
open: {
39+
<T extends Record<string, never>, R = any>(
40+
component:
41+
| ModalComponent<T, R>
42+
| (() => Promise<{ default: ModalComponent<T, R> }>),
43+
options?: ModalOptions
44+
): Promise<R>;
45+
<T, R = any>(
46+
component:
47+
| ModalComponent<T, R>
48+
| (() => Promise<{ default: ModalComponent<T, R> }>),
49+
props: Omit<T, keyof ModalProps<R>>,
50+
options?: ModalOptions
51+
): Promise<R>;
52+
};
4053
close: (n?: number) => boolean;
4154
closeById: (id: string) => boolean;
4255
closeAll: () => boolean;

src/use-modal-manager.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import { useState, useCallback, useRef } from "react";
1+
import { useCallback, useRef, useState } from "react";
22
import {
3-
ModalManager,
3+
ModalAction,
4+
ModalComponent,
45
ModalInstance,
6+
ModalManager,
57
ModalOptions,
6-
ModalAction,
8+
ModalProps,
79
} from "./types";
810

911
export function useModalManager(): ModalManager {
@@ -75,15 +77,15 @@ export function useModalManager(): ModalManager {
7577
const open = useCallback(
7678
<T = any, R = any>(
7779
component:
78-
| React.ComponentType<T>
79-
| (() => Promise<{ default: React.ComponentType<T> }>),
80-
data?: any,
80+
| ModalComponent<T, R>
81+
| (() => Promise<{ default: ModalComponent<T, R> }>),
82+
props?: Omit<T, keyof ModalProps<R>>,
8183
options?: ModalOptions
8284
): Promise<R> => {
8385
const id = options?.id || generateId();
8486

8587
return new Promise<R>(async (resolve) => {
86-
let actualComponent: React.ComponentType<T>;
88+
let actualComponent: ModalComponent<T, R>;
8789

8890
const isLazyImport =
8991
typeof component === "function" && !component.prototype;
@@ -92,7 +94,7 @@ export function useModalManager(): ModalManager {
9294
setIsLoading(true);
9395
try {
9496
const module = await (
95-
component as () => Promise<{ default: React.ComponentType<T> }>
97+
component as () => Promise<{ default: ModalComponent<T, R> }>
9698
)();
9799
actualComponent = module.default;
98100
} catch (error) {
@@ -101,29 +103,26 @@ export function useModalManager(): ModalManager {
101103
}
102104
setIsLoading(false);
103105
} else {
104-
actualComponent = component as React.ComponentType<T>;
106+
actualComponent = component as ModalComponent<T, R>;
105107
}
106108

107-
const newModalInstance: ModalInstance = {
109+
const newModalInstance: ModalInstance<T, R> = {
108110
component: actualComponent,
109111
id,
110112
isOpen: false,
111113
onBeforeClose: (callback: () => boolean) => {
112114
beforeCloseCallbacks.current.set(id, callback);
113115
},
114-
close: (value) => {
116+
close: (value?: R) => {
115117
if (canClose(id)) {
116-
resolve(value);
118+
resolve(value as R);
117119
closeCurrent(id);
118120
}
119121
},
122+
props,
120123
index: 0,
121124
};
122125

123-
if (data) {
124-
newModalInstance.data = data;
125-
}
126-
127126
setStack((prev) => {
128127
const existingModal = prev.find((modal) => modal.id === id);
129128
if (existingModal) {
@@ -151,6 +150,11 @@ export function useModalManager(): ModalManager {
151150

152151
const close = useCallback(
153152
(n: number = 1): boolean => {
153+
if (typeof n !== "number" || n < 1) {
154+
throw new Error(
155+
`amount must be a number greater than 0. Received ${n}`
156+
);
157+
}
154158
let closedCount = 0;
155159
setStack((prev) => {
156160
let newStack = [...prev];

0 commit comments

Comments
 (0)