@itcase/ui 1.8.169 → 1.8.170
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/dist/cjs/components/Modal.js +16 -9
- package/dist/components/Modal.js +17 -10
- package/package.json +1 -1
|
@@ -170,7 +170,9 @@ const Modal = React.forwardRef(function Modal(props, ref) {
|
|
|
170
170
|
}, [isOpen, isScrollOnOpen, isSetFocusOnOpen]);
|
|
171
171
|
// Show modal with children content
|
|
172
172
|
const openModal = React.useCallback(() => {
|
|
173
|
-
|
|
173
|
+
React.startTransition(() => {
|
|
174
|
+
setIsOpen(true);
|
|
175
|
+
});
|
|
174
176
|
// Callback
|
|
175
177
|
if (typeof onOpenModal === 'function') {
|
|
176
178
|
onOpenModal();
|
|
@@ -204,6 +206,12 @@ const Modal = React.forwardRef(function Modal(props, ref) {
|
|
|
204
206
|
// Callback
|
|
205
207
|
onCloseModal && onCloseModal();
|
|
206
208
|
}, [modalElement, onCloseModal]);
|
|
209
|
+
const handleClickOverlay = React.useCallback(() => {
|
|
210
|
+
if (isCloseOnBlur) {
|
|
211
|
+
closeModal();
|
|
212
|
+
}
|
|
213
|
+
onClickOverlay && onClickOverlay();
|
|
214
|
+
}, [closeModal, isCloseOnBlur, onClickOverlay]);
|
|
207
215
|
React.useEffect(() => {
|
|
208
216
|
if (!modalElement) {
|
|
209
217
|
return;
|
|
@@ -222,26 +230,25 @@ const Modal = React.forwardRef(function Modal(props, ref) {
|
|
|
222
230
|
}
|
|
223
231
|
}, [addModalProps, className, modalIdQuerySelector]);
|
|
224
232
|
React.useEffect(() => {
|
|
225
|
-
if (!isCloseOnBlur) {
|
|
233
|
+
if (!isCloseOnBlur || !isOpen) {
|
|
226
234
|
return;
|
|
227
235
|
}
|
|
228
236
|
const handleClickOutside = (event) => {
|
|
229
237
|
const target = event.target;
|
|
230
|
-
|
|
231
|
-
if (!modal || !target || !target.isConnected) {
|
|
238
|
+
if (!modalElement || !target || !target.isConnected) {
|
|
232
239
|
return;
|
|
233
240
|
}
|
|
234
|
-
const isOutside = !
|
|
241
|
+
const isOutside = !modalElement.contains(target);
|
|
235
242
|
if (isOutside) {
|
|
236
243
|
setIsOpen(false);
|
|
237
244
|
onCloseModal && onCloseModal();
|
|
238
245
|
}
|
|
239
246
|
};
|
|
240
|
-
|
|
247
|
+
window.addEventListener('click', handleClickOutside);
|
|
241
248
|
return () => {
|
|
242
|
-
|
|
249
|
+
window.removeEventListener('click', handleClickOutside);
|
|
243
250
|
};
|
|
244
|
-
}, [onCloseModal, isCloseOnBlur]);
|
|
251
|
+
}, [onCloseModal, isCloseOnBlur, isOpen, modalElement]);
|
|
245
252
|
// Save ref things
|
|
246
253
|
React.useImperativeHandle(ref, () => ({ modalElement, openModal, closeModal, isOpen }), [isOpen, openModal, closeModal, modalElement]);
|
|
247
254
|
const appearanceConfig = useAppearanceConfig.useAppearanceConfig(appearance, modalConfig, isDisabled);
|
|
@@ -255,7 +262,7 @@ const Modal = React.forwardRef(function Modal(props, ref) {
|
|
|
255
262
|
// Any valid React child: JSX, strings, arrays, etc.
|
|
256
263
|
isOpen ? (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsxs("div", { id: id, className: clsx('modal__content', absoluteHeader && 'modal__content-absolute-header', !title && !closeIcon && 'modal__content-no-header', fillClass && `fill_${fillClass}`, borderWidthClass && `border-width_${borderWidthClass}`, borderColorClass && `border-color_${borderColorClass}`, borderTypeClass && `border_type_${borderTypeClass}`, shapeClass && `shape_${shapeClass}`, sizeClass && `modal_size_${sizeClass}`, shapeStrengthClass && `shape-strength_${shapeStrengthClass}`, borderColorClass && `border-color_${borderColorClass}`, borderWidthClass && `border-width_${borderWidthClass}`, borderTypeClass && `border_type_${borderTypeClass}`, elevationClass && `elevation_${elevationClass}`, scroll && `modal-scroll_${scroll}`, stickyHeader && 'modal-scroll_header_sticky', isSkeleton && 'modal_skeleton'), ref: modalContentRef, "data-test-id": dataTestId, "data-tour": dataTour, style: modalStyles, tabIndex: 0, children: [(title || closeIcon) && (jsxRuntime.jsxs("div", { className: clsx('modal__header', fillClass && `fill_${fillClass}`), children: [title && (jsxRuntime.jsx(Icon.Title, { width: titleTextWidth, flex: "1", size: titleTextSize, textColor: titleTextColor, textColorHover: titleTextColorHover, textTruncate: titleTextTruncate, textWeight: titleTextWeight, textWrap: titleTextWrap, children: title })), closeIcon && (jsxRuntime.jsx("div", { className: "modal__close", onClick: closeModal, children: jsxRuntime.jsx(Icon.Icon, { appearance: `${closeIconAppearance} ${closeIconAppearanceSize}`, fillSize: closeIconFillSize, iconSize: closeIconSize, shape: closeIconShape, SvgImage: closeIconImage ?? _default.icons24.Action.Close }) }))] })), jsxRuntime.jsx("div", { className: "modal__content-wrapper", children: children })] }), jsxRuntime.jsx(Overlay.Overlay, { className: "modal__overlay",
|
|
257
264
|
// ref={modalOverlayRef}
|
|
258
|
-
fill: overlayFill, opacity: overlayOpacity, isOverlay: isOverlay, onClick:
|
|
265
|
+
fill: overlayFill, opacity: overlayOpacity, isOverlay: isOverlay, onClick: handleClickOverlay })] })) : null,
|
|
259
266
|
// A DOM element
|
|
260
267
|
modalElement));
|
|
261
268
|
});
|
package/dist/components/Modal.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import React, { useState, useRef, useCallback, useEffect, useLayoutEffect, useImperativeHandle } from 'react';
|
|
2
|
+
import React, { useState, useRef, useCallback, startTransition, useEffect, useLayoutEffect, useImperativeHandle } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
import ReactDOM from 'react-dom';
|
|
5
5
|
import { icons24, icons32, icons40 } from '@itcase/icons/default';
|
|
@@ -168,7 +168,9 @@ const Modal = React.forwardRef(function Modal(props, ref) {
|
|
|
168
168
|
}, [isOpen, isScrollOnOpen, isSetFocusOnOpen]);
|
|
169
169
|
// Show modal with children content
|
|
170
170
|
const openModal = useCallback(() => {
|
|
171
|
-
|
|
171
|
+
startTransition(() => {
|
|
172
|
+
setIsOpen(true);
|
|
173
|
+
});
|
|
172
174
|
// Callback
|
|
173
175
|
if (typeof onOpenModal === 'function') {
|
|
174
176
|
onOpenModal();
|
|
@@ -202,6 +204,12 @@ const Modal = React.forwardRef(function Modal(props, ref) {
|
|
|
202
204
|
// Callback
|
|
203
205
|
onCloseModal && onCloseModal();
|
|
204
206
|
}, [modalElement, onCloseModal]);
|
|
207
|
+
const handleClickOverlay = useCallback(() => {
|
|
208
|
+
if (isCloseOnBlur) {
|
|
209
|
+
closeModal();
|
|
210
|
+
}
|
|
211
|
+
onClickOverlay && onClickOverlay();
|
|
212
|
+
}, [closeModal, isCloseOnBlur, onClickOverlay]);
|
|
205
213
|
useEffect(() => {
|
|
206
214
|
if (!modalElement) {
|
|
207
215
|
return;
|
|
@@ -220,26 +228,25 @@ const Modal = React.forwardRef(function Modal(props, ref) {
|
|
|
220
228
|
}
|
|
221
229
|
}, [addModalProps, className, modalIdQuerySelector]);
|
|
222
230
|
useEffect(() => {
|
|
223
|
-
if (!isCloseOnBlur) {
|
|
231
|
+
if (!isCloseOnBlur || !isOpen) {
|
|
224
232
|
return;
|
|
225
233
|
}
|
|
226
234
|
const handleClickOutside = (event) => {
|
|
227
235
|
const target = event.target;
|
|
228
|
-
|
|
229
|
-
if (!modal || !target || !target.isConnected) {
|
|
236
|
+
if (!modalElement || !target || !target.isConnected) {
|
|
230
237
|
return;
|
|
231
238
|
}
|
|
232
|
-
const isOutside = !
|
|
239
|
+
const isOutside = !modalElement.contains(target);
|
|
233
240
|
if (isOutside) {
|
|
234
241
|
setIsOpen(false);
|
|
235
242
|
onCloseModal && onCloseModal();
|
|
236
243
|
}
|
|
237
244
|
};
|
|
238
|
-
|
|
245
|
+
window.addEventListener('click', handleClickOutside);
|
|
239
246
|
return () => {
|
|
240
|
-
|
|
247
|
+
window.removeEventListener('click', handleClickOutside);
|
|
241
248
|
};
|
|
242
|
-
}, [onCloseModal, isCloseOnBlur]);
|
|
249
|
+
}, [onCloseModal, isCloseOnBlur, isOpen, modalElement]);
|
|
243
250
|
// Save ref things
|
|
244
251
|
useImperativeHandle(ref, () => ({ modalElement, openModal, closeModal, isOpen }), [isOpen, openModal, closeModal, modalElement]);
|
|
245
252
|
const appearanceConfig = useAppearanceConfig(appearance, modalConfig, isDisabled);
|
|
@@ -253,7 +260,7 @@ const Modal = React.forwardRef(function Modal(props, ref) {
|
|
|
253
260
|
// Any valid React child: JSX, strings, arrays, etc.
|
|
254
261
|
isOpen ? (jsxs(React.Fragment, { children: [jsxs("div", { id: id, className: clsx('modal__content', absoluteHeader && 'modal__content-absolute-header', !title && !closeIcon && 'modal__content-no-header', fillClass && `fill_${fillClass}`, borderWidthClass && `border-width_${borderWidthClass}`, borderColorClass && `border-color_${borderColorClass}`, borderTypeClass && `border_type_${borderTypeClass}`, shapeClass && `shape_${shapeClass}`, sizeClass && `modal_size_${sizeClass}`, shapeStrengthClass && `shape-strength_${shapeStrengthClass}`, borderColorClass && `border-color_${borderColorClass}`, borderWidthClass && `border-width_${borderWidthClass}`, borderTypeClass && `border_type_${borderTypeClass}`, elevationClass && `elevation_${elevationClass}`, scroll && `modal-scroll_${scroll}`, stickyHeader && 'modal-scroll_header_sticky', isSkeleton && 'modal_skeleton'), ref: modalContentRef, "data-test-id": dataTestId, "data-tour": dataTour, style: modalStyles, tabIndex: 0, children: [(title || closeIcon) && (jsxs("div", { className: clsx('modal__header', fillClass && `fill_${fillClass}`), children: [title && (jsx(Title, { width: titleTextWidth, flex: "1", size: titleTextSize, textColor: titleTextColor, textColorHover: titleTextColorHover, textTruncate: titleTextTruncate, textWeight: titleTextWeight, textWrap: titleTextWrap, children: title })), closeIcon && (jsx("div", { className: "modal__close", onClick: closeModal, children: jsx(Icon, { appearance: `${closeIconAppearance} ${closeIconAppearanceSize}`, fillSize: closeIconFillSize, iconSize: closeIconSize, shape: closeIconShape, SvgImage: closeIconImage ?? icons24.Action.Close }) }))] })), jsx("div", { className: "modal__content-wrapper", children: children })] }), jsx(Overlay, { className: "modal__overlay",
|
|
255
262
|
// ref={modalOverlayRef}
|
|
256
|
-
fill: overlayFill, opacity: overlayOpacity, isOverlay: isOverlay, onClick:
|
|
263
|
+
fill: overlayFill, opacity: overlayOpacity, isOverlay: isOverlay, onClick: handleClickOverlay })] })) : null,
|
|
257
264
|
// A DOM element
|
|
258
265
|
modalElement));
|
|
259
266
|
});
|