@ehfuse/forma 2.0.4 → 2.0.6

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.
@@ -32,15 +32,20 @@ import { UseModalProps, UseModalReturn } from "../types/modal";
32
32
  * 모바일 환경에서 모달이 열려있을 때 뒤로가기를 누르면
33
33
  * 페이지가 뒤로 가는 것이 아니라 모달이 닫히도록 처리합니다.
34
34
  *
35
+ * 같은 modalId를 사용하면 여러 컴포넌트에서 같은 모달 상태를 공유합니다.
36
+ *
35
37
  * Handles modal state and back navigation.
36
38
  * When a modal is open and user presses back button,
37
39
  * the modal closes instead of navigating back.
38
40
  *
39
- * @param props - initialOpen: 초기 열림 상태, onClose: 닫힐 때 콜백
41
+ * Using the same modalId shares modal state across multiple components.
42
+ *
43
+ * @param props - modalId: 모달 ID (같은 ID면 공유), initialOpen: 초기 열림 상태, onClose: 닫힐 때 콜백
40
44
  * @returns isOpen, open, close, toggle, modalId
41
45
  *
42
46
  * @example
43
47
  * ```tsx
48
+ * // 독립적인 모달 (modalId 자동 생성)
44
49
  * function MyComponent() {
45
50
  * const modal = useModal({
46
51
  * onClose: () => console.log('Modal closed')
@@ -56,7 +61,22 @@ import { UseModalProps, UseModalReturn } from "../types/modal";
56
61
  * </>
57
62
  * );
58
63
  * }
64
+ *
65
+ * // 공유 모달 (같은 modalId 사용)
66
+ * function ComponentA() {
67
+ * const modal = useModal({ modalId: 'shared-modal' });
68
+ * return <button onClick={modal.open}>Open from A</button>;
69
+ * }
70
+ *
71
+ * function ComponentB() {
72
+ * const modal = useModal({ modalId: 'shared-modal' });
73
+ * return (
74
+ * <Dialog open={modal.isOpen} onClose={modal.close}>
75
+ * <DialogTitle>Shared Modal</DialogTitle>
76
+ * </Dialog>
77
+ * );
78
+ * }
59
79
  * ```
60
80
  */
61
- export declare function useModal({ initialOpen, onClose: externalOnClose, }?: UseModalProps): UseModalReturn;
81
+ export declare function useModal({ modalId: providedModalId, initialOpen, onClose: externalOnClose, }?: UseModalProps): UseModalReturn;
62
82
  //# sourceMappingURL=useModal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useModal.d.ts","sourceRoot":"","sources":["../../../hooks/useModal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAWH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAU/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,QAAQ,CAAC,EACrB,WAAmB,EACnB,OAAO,EAAE,eAAe,GAC3B,GAAE,aAAkB,GAAG,cAAc,CAuGrC"}
1
+ {"version":3,"file":"useModal.d.ts","sourceRoot":"","sources":["../../../hooks/useModal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAWH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAW/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAgB,QAAQ,CAAC,EACrB,OAAO,EAAE,eAAe,EACxB,WAAmB,EACnB,OAAO,EAAE,eAAe,GAC3B,GAAE,aAAkB,GAAG,cAAc,CA+GrC"}
@@ -25,8 +25,9 @@
25
25
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
26
  * SOFTWARE.
27
27
  */
28
- import { useState, useEffect, useCallback, useRef, useMemo, useContext, } from "react";
28
+ import { useEffect, useCallback, useRef, useMemo, useContext, } from "react";
29
29
  import { GlobalFormaContext } from "../contexts/GlobalFormaContext";
30
+ import { useGlobalFormaState } from "./useGlobalFormaState";
30
31
  /**
31
32
  * 모달 고유 ID 생성 함수
32
33
  * Generate unique modal ID
@@ -40,15 +41,20 @@ function generateModalId() {
40
41
  * 모바일 환경에서 모달이 열려있을 때 뒤로가기를 누르면
41
42
  * 페이지가 뒤로 가는 것이 아니라 모달이 닫히도록 처리합니다.
42
43
  *
44
+ * 같은 modalId를 사용하면 여러 컴포넌트에서 같은 모달 상태를 공유합니다.
45
+ *
43
46
  * Handles modal state and back navigation.
44
47
  * When a modal is open and user presses back button,
45
48
  * the modal closes instead of navigating back.
46
49
  *
47
- * @param props - initialOpen: 초기 열림 상태, onClose: 닫힐 때 콜백
50
+ * Using the same modalId shares modal state across multiple components.
51
+ *
52
+ * @param props - modalId: 모달 ID (같은 ID면 공유), initialOpen: 초기 열림 상태, onClose: 닫힐 때 콜백
48
53
  * @returns isOpen, open, close, toggle, modalId
49
54
  *
50
55
  * @example
51
56
  * ```tsx
57
+ * // 독립적인 모달 (modalId 자동 생성)
52
58
  * function MyComponent() {
53
59
  * const modal = useModal({
54
60
  * onClose: () => console.log('Modal closed')
@@ -64,13 +70,32 @@ function generateModalId() {
64
70
  * </>
65
71
  * );
66
72
  * }
73
+ *
74
+ * // 공유 모달 (같은 modalId 사용)
75
+ * function ComponentA() {
76
+ * const modal = useModal({ modalId: 'shared-modal' });
77
+ * return <button onClick={modal.open}>Open from A</button>;
78
+ * }
79
+ *
80
+ * function ComponentB() {
81
+ * const modal = useModal({ modalId: 'shared-modal' });
82
+ * return (
83
+ * <Dialog open={modal.isOpen} onClose={modal.close}>
84
+ * <DialogTitle>Shared Modal</DialogTitle>
85
+ * </Dialog>
86
+ * );
87
+ * }
67
88
  * ```
68
89
  */
69
- export function useModal({ initialOpen = false, onClose: externalOnClose, } = {}) {
70
- // 고유 ID 생성
71
- const modalId = useMemo(() => generateModalId(), []);
72
- // 모달 상태 관리
73
- const [isOpen, setIsOpen] = useState(initialOpen);
90
+ export function useModal({ modalId: providedModalId, initialOpen = false, onClose: externalOnClose, } = {}) {
91
+ // modalId가 제공되면 사용, 아니면 고유 ID 생성
92
+ const modalId = useMemo(() => providedModalId || generateModalId(), [providedModalId]);
93
+ // 전역 상태로 모달 열림 상태 관리 (reactive!)
94
+ const state = useGlobalFormaState({
95
+ stateId: `__modal_${modalId}__`,
96
+ initialValues: { isOpen: initialOpen },
97
+ });
98
+ const isOpen = state.useValue("isOpen");
74
99
  const { appendOpenModal, removeOpenModal } = useContext(GlobalFormaContext);
75
100
  // 이미 등록된 모달인지 추적
76
101
  const isRegisteredRef = useRef(false);
@@ -82,13 +107,13 @@ export function useModal({ initialOpen = false, onClose: externalOnClose, } = {}
82
107
  // 모달 열기
83
108
  const open = useCallback(() => {
84
109
  if (!isOpen) {
85
- setIsOpen(true);
110
+ state.setValue("isOpen", true);
86
111
  if (!isRegisteredRef.current) {
87
112
  appendOpenModal(modalId);
88
113
  isRegisteredRef.current = true;
89
114
  }
90
115
  }
91
- }, [isOpen, modalId, appendOpenModal]);
116
+ }, [isOpen, modalId, appendOpenModal, state]);
92
117
  // 모달 닫기
93
118
  const close = useCallback(() => {
94
119
  if (isOpen) {
@@ -96,17 +121,17 @@ export function useModal({ initialOpen = false, onClose: externalOnClose, } = {}
96
121
  if (isRegisteredRef.current) {
97
122
  window.history.back();
98
123
  // popstate 이벤트가 발생하면 FormContext의 handlePopState가 처리하여
99
- // closeLastModal -> modal:close 이벤트 발생 -> handleCloseEvent 에서 setIsOpen(false) 호출
124
+ // closeLastModal -> modal:close 이벤트 발생 -> handleCloseEvent 에서 state.setValue("isOpen", false) 호출
100
125
  }
101
126
  else {
102
127
  // 등록되지 않은 경우 (open()이 호출되지 않고 직접 닫히는 경우) 직접 닫기
103
- setIsOpen(false);
128
+ state.setValue("isOpen", false);
104
129
  if (onCloseRef.current) {
105
130
  onCloseRef.current();
106
131
  }
107
132
  }
108
133
  }
109
- }, [isOpen]);
134
+ }, [isOpen, state]);
110
135
  // 모달 토글
111
136
  const toggle = useCallback(() => {
112
137
  if (isOpen) {
@@ -130,8 +155,8 @@ export function useModal({ initialOpen = false, onClose: externalOnClose, } = {}
130
155
  // 외부에서 모달 닫기 요청을 처리하는 이벤트 리스너
131
156
  const handleCloseEvent = () => {
132
157
  // 이벤트가 수신될때는 popstate가 발생한 것이므로 히스토리는 이미 삭제된 상태라서 닫기만 실행
133
- setIsOpen(false);
134
- // 모달 제거 - 이 부분이 누락되어 있었습니다!
158
+ state.setValue("isOpen", false);
159
+ // 모달 제거
135
160
  if (isRegisteredRef.current) {
136
161
  removeOpenModal(modalId);
137
162
  isRegisteredRef.current = false;
@@ -146,7 +171,7 @@ export function useModal({ initialOpen = false, onClose: externalOnClose, } = {}
146
171
  return () => {
147
172
  window.removeEventListener(`modal:close:${modalId}`, handleCloseEvent);
148
173
  };
149
- }, [modalId, removeOpenModal]);
174
+ }, [modalId, removeOpenModal, state]);
150
175
  return {
151
176
  isOpen,
152
177
  open,
@@ -1 +1 @@
1
- {"version":3,"file":"useModal.js","sourceRoot":"","sources":["../../../hooks/useModal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useModal.js","sourceRoot":"","sources":["../../../hooks/useModal.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,20 @@
11
11
  * useModal 훅의 속성 인터페이스 | useModal hook properties interface
12
12
  */
13
13
  export interface UseModalProps {
14
+ /**
15
+ * 모달의 고유 ID. 같은 ID를 사용하면 같은 모달 인스턴스를 공유합니다.
16
+ * Modal unique ID. Using the same ID shares the same modal instance.
17
+ */
18
+ modalId?: string;
19
+ /**
20
+ * 초기 열림 상태 (기본값: false)
21
+ * Initial open state (default: false)
22
+ */
14
23
  initialOpen?: boolean;
24
+ /**
25
+ * 모달이 닫힐 때 호출되는 콜백
26
+ * Callback called when modal closes
27
+ */
15
28
  onClose?: () => void;
16
29
  }
17
30
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../types/modal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../types/modal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACnB"}
@@ -32,15 +32,20 @@ import { UseModalProps, UseModalReturn } from "../types/modal";
32
32
  * 모바일 환경에서 모달이 열려있을 때 뒤로가기를 누르면
33
33
  * 페이지가 뒤로 가는 것이 아니라 모달이 닫히도록 처리합니다.
34
34
  *
35
+ * 같은 modalId를 사용하면 여러 컴포넌트에서 같은 모달 상태를 공유합니다.
36
+ *
35
37
  * Handles modal state and back navigation.
36
38
  * When a modal is open and user presses back button,
37
39
  * the modal closes instead of navigating back.
38
40
  *
39
- * @param props - initialOpen: 초기 열림 상태, onClose: 닫힐 때 콜백
41
+ * Using the same modalId shares modal state across multiple components.
42
+ *
43
+ * @param props - modalId: 모달 ID (같은 ID면 공유), initialOpen: 초기 열림 상태, onClose: 닫힐 때 콜백
40
44
  * @returns isOpen, open, close, toggle, modalId
41
45
  *
42
46
  * @example
43
47
  * ```tsx
48
+ * // 독립적인 모달 (modalId 자동 생성)
44
49
  * function MyComponent() {
45
50
  * const modal = useModal({
46
51
  * onClose: () => console.log('Modal closed')
@@ -56,7 +61,22 @@ import { UseModalProps, UseModalReturn } from "../types/modal";
56
61
  * </>
57
62
  * );
58
63
  * }
64
+ *
65
+ * // 공유 모달 (같은 modalId 사용)
66
+ * function ComponentA() {
67
+ * const modal = useModal({ modalId: 'shared-modal' });
68
+ * return <button onClick={modal.open}>Open from A</button>;
69
+ * }
70
+ *
71
+ * function ComponentB() {
72
+ * const modal = useModal({ modalId: 'shared-modal' });
73
+ * return (
74
+ * <Dialog open={modal.isOpen} onClose={modal.close}>
75
+ * <DialogTitle>Shared Modal</DialogTitle>
76
+ * </Dialog>
77
+ * );
78
+ * }
59
79
  * ```
60
80
  */
61
- export declare function useModal({ initialOpen, onClose: externalOnClose, }?: UseModalProps): UseModalReturn;
81
+ export declare function useModal({ modalId: providedModalId, initialOpen, onClose: externalOnClose, }?: UseModalProps): UseModalReturn;
62
82
  //# sourceMappingURL=useModal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useModal.d.ts","sourceRoot":"","sources":["../../hooks/useModal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAWH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAU/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,QAAQ,CAAC,EACrB,WAAmB,EACnB,OAAO,EAAE,eAAe,GAC3B,GAAE,aAAkB,GAAG,cAAc,CAuGrC"}
1
+ {"version":3,"file":"useModal.d.ts","sourceRoot":"","sources":["../../hooks/useModal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAWH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAW/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAgB,QAAQ,CAAC,EACrB,OAAO,EAAE,eAAe,EACxB,WAAmB,EACnB,OAAO,EAAE,eAAe,GAC3B,GAAE,aAAkB,GAAG,cAAc,CA+GrC"}
@@ -30,6 +30,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
30
30
  exports.useModal = useModal;
31
31
  const react_1 = require("react");
32
32
  const GlobalFormaContext_1 = require("../contexts/GlobalFormaContext");
33
+ const useGlobalFormaState_1 = require("./useGlobalFormaState");
33
34
  /**
34
35
  * 모달 고유 ID 생성 함수
35
36
  * Generate unique modal ID
@@ -43,15 +44,20 @@ function generateModalId() {
43
44
  * 모바일 환경에서 모달이 열려있을 때 뒤로가기를 누르면
44
45
  * 페이지가 뒤로 가는 것이 아니라 모달이 닫히도록 처리합니다.
45
46
  *
47
+ * 같은 modalId를 사용하면 여러 컴포넌트에서 같은 모달 상태를 공유합니다.
48
+ *
46
49
  * Handles modal state and back navigation.
47
50
  * When a modal is open and user presses back button,
48
51
  * the modal closes instead of navigating back.
49
52
  *
50
- * @param props - initialOpen: 초기 열림 상태, onClose: 닫힐 때 콜백
53
+ * Using the same modalId shares modal state across multiple components.
54
+ *
55
+ * @param props - modalId: 모달 ID (같은 ID면 공유), initialOpen: 초기 열림 상태, onClose: 닫힐 때 콜백
51
56
  * @returns isOpen, open, close, toggle, modalId
52
57
  *
53
58
  * @example
54
59
  * ```tsx
60
+ * // 독립적인 모달 (modalId 자동 생성)
55
61
  * function MyComponent() {
56
62
  * const modal = useModal({
57
63
  * onClose: () => console.log('Modal closed')
@@ -67,13 +73,32 @@ function generateModalId() {
67
73
  * </>
68
74
  * );
69
75
  * }
76
+ *
77
+ * // 공유 모달 (같은 modalId 사용)
78
+ * function ComponentA() {
79
+ * const modal = useModal({ modalId: 'shared-modal' });
80
+ * return <button onClick={modal.open}>Open from A</button>;
81
+ * }
82
+ *
83
+ * function ComponentB() {
84
+ * const modal = useModal({ modalId: 'shared-modal' });
85
+ * return (
86
+ * <Dialog open={modal.isOpen} onClose={modal.close}>
87
+ * <DialogTitle>Shared Modal</DialogTitle>
88
+ * </Dialog>
89
+ * );
90
+ * }
70
91
  * ```
71
92
  */
72
- function useModal({ initialOpen = false, onClose: externalOnClose, } = {}) {
73
- // 고유 ID 생성
74
- const modalId = (0, react_1.useMemo)(() => generateModalId(), []);
75
- // 모달 상태 관리
76
- const [isOpen, setIsOpen] = (0, react_1.useState)(initialOpen);
93
+ function useModal({ modalId: providedModalId, initialOpen = false, onClose: externalOnClose, } = {}) {
94
+ // modalId가 제공되면 사용, 아니면 고유 ID 생성
95
+ const modalId = (0, react_1.useMemo)(() => providedModalId || generateModalId(), [providedModalId]);
96
+ // 전역 상태로 모달 열림 상태 관리 (reactive!)
97
+ const state = (0, useGlobalFormaState_1.useGlobalFormaState)({
98
+ stateId: `__modal_${modalId}__`,
99
+ initialValues: { isOpen: initialOpen },
100
+ });
101
+ const isOpen = state.useValue("isOpen");
77
102
  const { appendOpenModal, removeOpenModal } = (0, react_1.useContext)(GlobalFormaContext_1.GlobalFormaContext);
78
103
  // 이미 등록된 모달인지 추적
79
104
  const isRegisteredRef = (0, react_1.useRef)(false);
@@ -85,13 +110,13 @@ function useModal({ initialOpen = false, onClose: externalOnClose, } = {}) {
85
110
  // 모달 열기
86
111
  const open = (0, react_1.useCallback)(() => {
87
112
  if (!isOpen) {
88
- setIsOpen(true);
113
+ state.setValue("isOpen", true);
89
114
  if (!isRegisteredRef.current) {
90
115
  appendOpenModal(modalId);
91
116
  isRegisteredRef.current = true;
92
117
  }
93
118
  }
94
- }, [isOpen, modalId, appendOpenModal]);
119
+ }, [isOpen, modalId, appendOpenModal, state]);
95
120
  // 모달 닫기
96
121
  const close = (0, react_1.useCallback)(() => {
97
122
  if (isOpen) {
@@ -99,17 +124,17 @@ function useModal({ initialOpen = false, onClose: externalOnClose, } = {}) {
99
124
  if (isRegisteredRef.current) {
100
125
  window.history.back();
101
126
  // popstate 이벤트가 발생하면 FormContext의 handlePopState가 처리하여
102
- // closeLastModal -> modal:close 이벤트 발생 -> handleCloseEvent 에서 setIsOpen(false) 호출
127
+ // closeLastModal -> modal:close 이벤트 발생 -> handleCloseEvent 에서 state.setValue("isOpen", false) 호출
103
128
  }
104
129
  else {
105
130
  // 등록되지 않은 경우 (open()이 호출되지 않고 직접 닫히는 경우) 직접 닫기
106
- setIsOpen(false);
131
+ state.setValue("isOpen", false);
107
132
  if (onCloseRef.current) {
108
133
  onCloseRef.current();
109
134
  }
110
135
  }
111
136
  }
112
- }, [isOpen]);
137
+ }, [isOpen, state]);
113
138
  // 모달 토글
114
139
  const toggle = (0, react_1.useCallback)(() => {
115
140
  if (isOpen) {
@@ -133,8 +158,8 @@ function useModal({ initialOpen = false, onClose: externalOnClose, } = {}) {
133
158
  // 외부에서 모달 닫기 요청을 처리하는 이벤트 리스너
134
159
  const handleCloseEvent = () => {
135
160
  // 이벤트가 수신될때는 popstate가 발생한 것이므로 히스토리는 이미 삭제된 상태라서 닫기만 실행
136
- setIsOpen(false);
137
- // 모달 제거 - 이 부분이 누락되어 있었습니다!
161
+ state.setValue("isOpen", false);
162
+ // 모달 제거
138
163
  if (isRegisteredRef.current) {
139
164
  removeOpenModal(modalId);
140
165
  isRegisteredRef.current = false;
@@ -149,7 +174,7 @@ function useModal({ initialOpen = false, onClose: externalOnClose, } = {}) {
149
174
  return () => {
150
175
  window.removeEventListener(`modal:close:${modalId}`, handleCloseEvent);
151
176
  };
152
- }, [modalId, removeOpenModal]);
177
+ }, [modalId, removeOpenModal, state]);
153
178
  return {
154
179
  isOpen,
155
180
  open,
@@ -1 +1 @@
1
- {"version":3,"file":"useModal.js","sourceRoot":"","sources":["../../hooks/useModal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useModal.js","sourceRoot":"","sources":["../../hooks/useModal.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,20 @@
11
11
  * useModal 훅의 속성 인터페이스 | useModal hook properties interface
12
12
  */
13
13
  export interface UseModalProps {
14
+ /**
15
+ * 모달의 고유 ID. 같은 ID를 사용하면 같은 모달 인스턴스를 공유합니다.
16
+ * Modal unique ID. Using the same ID shares the same modal instance.
17
+ */
18
+ modalId?: string;
19
+ /**
20
+ * 초기 열림 상태 (기본값: false)
21
+ * Initial open state (default: false)
22
+ */
14
23
  initialOpen?: boolean;
24
+ /**
25
+ * 모달이 닫힐 때 호출되는 콜백
26
+ * Callback called when modal closes
27
+ */
15
28
  onClose?: () => void;
16
29
  }
17
30
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../types/modal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../types/modal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACnB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ehfuse/forma",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "Advanced React state management library with individual field subscriptions - supports both forms and general state management with useFormaState",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",