@orangesk/orange-design-system 2.0.0-beta.26 → 2.0.0-beta.28

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.
@@ -1,14 +1,12 @@
1
1
  "use client";
2
2
 
3
- import React, { useEffect } from "react";
3
+ import React, { useEffect, useMemo } from "react";
4
4
  import cx from "classnames";
5
5
 
6
6
  import { useStatic } from "../../utils/hooks";
7
7
  import ConditionalWrapper from "../../utils/ConditionalWrapper";
8
8
  import { Button } from "../Button";
9
9
  import { Buttons } from "../Buttons";
10
-
11
- // Use JavaScript version for now, then convert to TypeScript later
12
10
  import ModalStatic from "./Modal.static";
13
11
  import { ModalCloseButton } from "./ModalCloseButton";
14
12
  import { ModalTitle } from "./ModalTitle";
@@ -31,8 +29,8 @@ interface ModalProps extends React.HTMLAttributes<HTMLDivElement> {
31
29
  id: string;
32
30
  /** isActive controls if modal is opened or closed */
33
31
  isActive?: boolean;
34
- /** Disable plugin initialization. */
35
- noInit?: boolean;
32
+ /** Callback fired when modal is closed */
33
+ onHide?: () => void;
36
34
  /** Custom header renderer. Receives id as function param. Returned element(s) must contain a header with close button. */
37
35
  renderHeader?: (id: string) => React.ReactNode;
38
36
  /** Custom body renderer. Receives title as function param. Returned element(s) must contain a title. */
@@ -61,7 +59,6 @@ const defaultProps = {
61
59
  Zatvoriť
62
60
  </Button>,
63
61
  ],
64
- noInit: false,
65
62
  };
66
63
 
67
64
  const Modal: React.FC<ModalProps> = ({
@@ -70,8 +67,8 @@ const Modal: React.FC<ModalProps> = ({
70
67
  children,
71
68
  hasStickyFooter,
72
69
  id,
73
- noInit = defaultProps.noInit,
74
70
  isActive,
71
+ onHide,
75
72
  size,
76
73
  title,
77
74
  renderHeader,
@@ -83,12 +80,38 @@ const Modal: React.FC<ModalProps> = ({
83
80
  disableFooterSpacing,
84
81
  ...other
85
82
  }) => {
86
- const modalConfig = isActive !== undefined ? { disablePortal: true } : {};
83
+ // In React controlled mode (using isActive), we skip data-modal
84
+ // so vanilla JS won't initialize and move modal to #root-modals
85
+ // onHide alone works in uncontrolled mode - it's just a callback
86
+ const isReactControlled = isActive !== undefined;
87
+
88
+ const modalConfig = useMemo(
89
+ () => (isReactControlled ? { disablePortal: true } : {}),
90
+ [isReactControlled],
91
+ );
87
92
  const [modalRef, instance] = useStatic(ModalStatic, modalConfig);
88
93
 
89
94
  useEffect(() => {
90
- if (isActive && instance && (instance as any).current) {
91
- (instance as any).current.show();
95
+ if (!instance.current || !onHide) return;
96
+
97
+ const handleHide = () => {
98
+ onHide();
99
+ };
100
+
101
+ instance.current.instance.on("hide", handleHide);
102
+
103
+ return () => {
104
+ instance.current?.instance.off("hide", handleHide);
105
+ };
106
+ }, [instance, onHide]);
107
+
108
+ useEffect(() => {
109
+ if (!instance.current) return;
110
+
111
+ if (isActive) {
112
+ instance.current.show();
113
+ } else if (isActive === false) {
114
+ instance.current.hide();
92
115
  }
93
116
  }, [instance, isActive]);
94
117
 
@@ -114,7 +137,7 @@ const Modal: React.FC<ModalProps> = ({
114
137
  return (
115
138
  <div
116
139
  id={id}
117
- data-modal={!noInit}
140
+ {...(!isReactControlled && { "data-modal": true })}
118
141
  className={CLASS_ROOT}
119
142
  ref={modalRef}
120
143
  role="dialog"
@@ -124,7 +147,6 @@ const Modal: React.FC<ModalProps> = ({
124
147
  >
125
148
  <div className="modal__overlay" tabIndex={-1} data-a11y-dialog-hide />
126
149
  <div className={dialogClasses} role="document" {...other}>
127
- {}
128
150
  <div
129
151
  className={cx(`${CLASS_ROOT}__header`, {
130
152
  [`${CLASS_ROOT}__header--no-spacing`]: disableHeaderSpacing,