@hh.ru/magritte-ui-modal 3.0.14
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/Modal.d.ts +20 -0
- package/Modal.js +122 -0
- package/Modal.js.map +1 -0
- package/ModalContentWithHeader.d.ts +5 -0
- package/ModalContentWithHeader.js +52 -0
- package/ModalContentWithHeader.js.map +1 -0
- package/ModalFooter.d.ts +3 -0
- package/ModalFooter.js +13 -0
- package/ModalFooter.js.map +1 -0
- package/ModalHeader.d.ts +5 -0
- package/ModalHeader.js +32 -0
- package/ModalHeader.js.map +1 -0
- package/index.css +185 -0
- package/index.d.ts +2 -0
- package/index.js +25 -0
- package/index.js.map +1 -0
- package/index.mock.d.ts +4 -0
- package/index.mock.js +11 -0
- package/index.mock.js.map +1 -0
- package/modal-198e0f95.js +5 -0
- package/modal-198e0f95.js.map +1 -0
- package/package.json +49 -0
- package/types.d.ts +57 -0
- package/types.js +3 -0
- package/types.js.map +1 -0
- package/useModalOrder.d.ts +2 -0
- package/useModalOrder.js +90 -0
- package/useModalOrder.js.map +1 -0
package/Modal.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
|
+
import { ModalProps } from './types';
|
|
3
|
+
export declare const Modal: import("react").ForwardRefExoticComponent<(ModalProps & Omit<HTMLAttributes<HTMLDivElement>, keyof {
|
|
4
|
+
headerImage: string;
|
|
5
|
+
headerHeight?: number | undefined;
|
|
6
|
+
} | keyof {
|
|
7
|
+
title: import("react").ReactNode;
|
|
8
|
+
titleSize?: import("../title/src/types").TitleSizeOptions | undefined;
|
|
9
|
+
titleAlignment?: "center" | "left" | undefined;
|
|
10
|
+
titleMaxLines?: number | undefined;
|
|
11
|
+
titleElement?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | undefined;
|
|
12
|
+
titleDescription?: import("react").ReactNode;
|
|
13
|
+
titleDescriptionMaxLines?: number | undefined;
|
|
14
|
+
titleStyle?: ("primary" | "secondary" | "tertiary" | "contrast" | "contrast-secondary") | undefined;
|
|
15
|
+
titleDescriptionStyle?: ("primary" | "secondary" | "tertiary" | "contrast" | "contrast-secondary") | undefined;
|
|
16
|
+
} | "className" | keyof {
|
|
17
|
+
options?: import("react").ReactNode;
|
|
18
|
+
actions?: import("react").ReactNode | import("react").ReactNode[];
|
|
19
|
+
actionLink?: import("react").ReactNode;
|
|
20
|
+
} | keyof import("./types").ModalBaseProps | keyof import("@hh.ru/magritte-ui-modal/types").ModalFooterProps | "role" | "tabindex" | "aria-labeledby">) & import("react").RefAttributes<HTMLDivElement>>;
|
package/Modal.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import { forwardRef, useRef, useState, useId, useCallback, useEffect, useLayoutEffect } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { CSSTransition } from 'react-transition-group';
|
|
6
|
+
import classnames from 'classnames';
|
|
7
|
+
import { useServerEnv } from '@hh.ru/magritte-common-is-server-env';
|
|
8
|
+
import { keyboardMatch, keyboardKeys } from '@hh.ru/magritte-common-keyboard';
|
|
9
|
+
import { disableScroll } from '@hh.ru/magritte-common-modal-helper';
|
|
10
|
+
import { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';
|
|
11
|
+
import { InternalLayerName } from '@hh.ru/magritte-internal-layer-name';
|
|
12
|
+
import { Breakpoint, useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';
|
|
13
|
+
import { Layer } from '@hh.ru/magritte-ui-layer';
|
|
14
|
+
import { ModalContentWithHeader } from './ModalContentWithHeader.js';
|
|
15
|
+
import { ModalFooter } from './ModalFooter.js';
|
|
16
|
+
import { useModalOrder } from './useModalOrder.js';
|
|
17
|
+
import { s as styles } from './modal-198e0f95.js';
|
|
18
|
+
import '@hh.ru/magritte-common-func-utils';
|
|
19
|
+
import '@hh.ru/magritte-ui-divider';
|
|
20
|
+
import './ModalHeader.js';
|
|
21
|
+
import '@hh.ru/magritte-ui-title';
|
|
22
|
+
import '@hh.ru/magritte-common-dom-storage';
|
|
23
|
+
|
|
24
|
+
const noop = () => undefined;
|
|
25
|
+
const toNumber = (value) => {
|
|
26
|
+
const result = parseInt(value, 10);
|
|
27
|
+
return Number.isInteger(result) ? result : 0;
|
|
28
|
+
};
|
|
29
|
+
const INVISIBLE_FOR_BREAKPOINTS = [Breakpoint.XS, Breakpoint.S];
|
|
30
|
+
const Modal = forwardRef(({ visible, size = 'medium', title, titleAlignment = 'left', titleSize = 'large', titleMaxLines, titleElement = 'h2', titleDescription, titleDescriptionMaxLines, titleStyle, titleDescriptionStyle, children, onClose = noop, leftButtons, rightButtons, headerImage, headerHeight, host, options, actions, actionLink, ...rest }, ref) => {
|
|
31
|
+
const isServerEnv = useServerEnv();
|
|
32
|
+
const enableScrollRef = useRef();
|
|
33
|
+
const [animationTimeout, setAnimationTimeout] = useState({
|
|
34
|
+
enter: 0,
|
|
35
|
+
exit: 0,
|
|
36
|
+
});
|
|
37
|
+
const labelId = useId();
|
|
38
|
+
const additionalProps = {};
|
|
39
|
+
if (title) {
|
|
40
|
+
additionalProps['aria-labelledby'] = labelId;
|
|
41
|
+
}
|
|
42
|
+
const modalRef = useRef(null);
|
|
43
|
+
const overlayRef = useRef(null);
|
|
44
|
+
const modalRefCallback = useMultipleRefs(ref, modalRef);
|
|
45
|
+
const onEntering = useCallback(() => {
|
|
46
|
+
if (!enableScrollRef.current) {
|
|
47
|
+
enableScrollRef.current = disableScroll();
|
|
48
|
+
}
|
|
49
|
+
if (modalRef.current && !modalRef.current.contains(document.activeElement)) {
|
|
50
|
+
modalRef.current.focus();
|
|
51
|
+
}
|
|
52
|
+
}, []);
|
|
53
|
+
const onExited = useCallback(() => {
|
|
54
|
+
enableScrollRef.current?.();
|
|
55
|
+
enableScrollRef.current = undefined;
|
|
56
|
+
}, []);
|
|
57
|
+
const [position, count] = useModalOrder(!!visible && !isServerEnv, modalRef);
|
|
58
|
+
const isOverlayHidden = (position === 0 && count > 0) || (count > 1 && position > 1);
|
|
59
|
+
const { breakpoint } = useBreakpoint();
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!visible) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const currentBreakpointVisible = !INVISIBLE_FOR_BREAKPOINTS.includes(breakpoint);
|
|
65
|
+
if (!currentBreakpointVisible) {
|
|
66
|
+
onExited();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
onEntering();
|
|
70
|
+
// visible не должно быть в зависимостях, т.к. этот эффект обрабатывает только изменение брейкпоинта
|
|
71
|
+
// visible обрабатывается CSSTransition
|
|
72
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
+
}, [breakpoint, onEntering, onExited]);
|
|
74
|
+
useEffect(() => () => {
|
|
75
|
+
enableScrollRef.current?.();
|
|
76
|
+
enableScrollRef.current = undefined;
|
|
77
|
+
}, [visible]);
|
|
78
|
+
useLayoutEffect(() => {
|
|
79
|
+
const animationTimeoutElement = document.createElement('div');
|
|
80
|
+
animationTimeoutElement.classList.add(styles.animationTimeout);
|
|
81
|
+
document.body.appendChild(animationTimeoutElement);
|
|
82
|
+
const style = window.getComputedStyle(animationTimeoutElement);
|
|
83
|
+
setAnimationTimeout({
|
|
84
|
+
enter: toNumber(style.getPropertyValue('--enter-animation-duration')),
|
|
85
|
+
exit: toNumber(style.getPropertyValue('--exit-animation-duration')),
|
|
86
|
+
});
|
|
87
|
+
document.body.removeChild(animationTimeoutElement);
|
|
88
|
+
}, [setAnimationTimeout]);
|
|
89
|
+
if (INVISIBLE_FOR_BREAKPOINTS.includes(breakpoint) || isServerEnv) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const modalHeaderProps = {
|
|
93
|
+
title,
|
|
94
|
+
titleElement,
|
|
95
|
+
titleAlignment,
|
|
96
|
+
titleSize,
|
|
97
|
+
titleMaxLines,
|
|
98
|
+
titleDescription,
|
|
99
|
+
titleDescriptionMaxLines,
|
|
100
|
+
titleStyle,
|
|
101
|
+
titleDescriptionStyle,
|
|
102
|
+
headerImage,
|
|
103
|
+
headerHeight,
|
|
104
|
+
options,
|
|
105
|
+
actions,
|
|
106
|
+
actionLink,
|
|
107
|
+
};
|
|
108
|
+
return createPortal(jsx(CSSTransition, { in: visible && !isServerEnv, nodeRef: overlayRef, onEntering: onEntering, onExited: onExited, classNames: {
|
|
109
|
+
enter: styles.modalAnimationEnter,
|
|
110
|
+
enterActive: styles.modalAnimationEnterActive,
|
|
111
|
+
exit: styles.modalAnimationExit,
|
|
112
|
+
exitActive: styles.modalAnimationExitActive,
|
|
113
|
+
}, timeout: animationTimeout, unmountOnExit: true, children: jsx(Layer, { layer: InternalLayerName.Modal, children: jsx("div", { ref: overlayRef, className: styles.modalOverlay, style: isOverlayHidden ? { backgroundColor: 'transparent' } : {}, onKeyDown: (event) => {
|
|
114
|
+
if (keyboardMatch(event.nativeEvent, keyboardKeys.Escape)) {
|
|
115
|
+
onClose();
|
|
116
|
+
}
|
|
117
|
+
}, "data-qa": "modal-overlay", children: jsxs("div", { ...rest, ...additionalProps, role: "dialog", className: classnames(styles.modal, { [styles.modalSmall]: size === 'small' }), ref: modalRefCallback, tabIndex: 0, children: [jsx(ModalContentWithHeader, { ...modalHeaderProps, labelId: labelId, children: children }), jsx(ModalFooter, { leftButtons: leftButtons, rightButtons: rightButtons })] }) }) }) }), host || document.body);
|
|
118
|
+
});
|
|
119
|
+
Modal.displayName = 'Modal';
|
|
120
|
+
|
|
121
|
+
export { Modal };
|
|
122
|
+
//# sourceMappingURL=Modal.js.map
|
package/Modal.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.js","sources":["../src/Modal.tsx"],"sourcesContent":["import { forwardRef, HTMLAttributes, useLayoutEffect, useRef, useState, useCallback, useId, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { CSSTransition } from 'react-transition-group';\nimport classnames from 'classnames';\n\nimport { useServerEnv } from '@hh.ru/magritte-common-is-server-env';\nimport { keyboardMatch, keyboardKeys } from '@hh.ru/magritte-common-keyboard';\nimport { disableScroll } from '@hh.ru/magritte-common-modal-helper';\nimport { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';\nimport { InternalLayerName } from '@hh.ru/magritte-internal-layer-name';\nimport { useBreakpoint, Breakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { Layer } from '@hh.ru/magritte-ui-layer';\nimport { ModalContentWithHeader } from '@hh.ru/magritte-ui-modal/ModalContentWithHeader';\nimport { ModalFooter } from '@hh.ru/magritte-ui-modal/ModalFooter';\nimport { ModalHeaderProps, ModalProps } from '@hh.ru/magritte-ui-modal/types';\nimport { useModalOrder } from '@hh.ru/magritte-ui-modal/useModalOrder';\n\nimport styles from './modal.less';\n\nconst noop = () => undefined;\n\nconst toNumber = (value: string) => {\n const result = parseInt(value, 10);\n return Number.isInteger(result) ? result : 0;\n};\n\nconst INVISIBLE_FOR_BREAKPOINTS = [Breakpoint.XS, Breakpoint.S];\n\nexport const Modal = forwardRef<\n HTMLDivElement,\n ModalProps &\n Omit<HTMLAttributes<HTMLDivElement>, keyof ModalProps | 'role' | 'tabindex' | 'className' | 'aria-labeledby'>\n>(\n (\n {\n visible,\n size = 'medium',\n title,\n titleAlignment = 'left',\n titleSize = 'large',\n titleMaxLines,\n titleElement = 'h2',\n titleDescription,\n titleDescriptionMaxLines,\n titleStyle,\n titleDescriptionStyle,\n children,\n onClose = noop,\n leftButtons,\n rightButtons,\n headerImage,\n headerHeight,\n host,\n options,\n actions,\n actionLink,\n ...rest\n },\n ref\n ) => {\n const isServerEnv = useServerEnv();\n const enableScrollRef = useRef<() => void>();\n const [animationTimeout, setAnimationTimeout] = useState<{ enter: number; exit: number }>({\n enter: 0,\n exit: 0,\n });\n const labelId = useId();\n const additionalProps: { 'aria-labelledby'?: string } = {};\n if (title) {\n additionalProps['aria-labelledby'] = labelId;\n }\n const modalRef = useRef<HTMLDivElement>(null);\n const overlayRef = useRef<HTMLDivElement>(null);\n const modalRefCallback = useMultipleRefs(ref, modalRef);\n\n const onEntering = useCallback(() => {\n if (!enableScrollRef.current) {\n enableScrollRef.current = disableScroll();\n }\n if (modalRef.current && !modalRef.current.contains(document.activeElement)) {\n modalRef.current.focus();\n }\n }, []);\n const onExited = useCallback(() => {\n enableScrollRef.current?.();\n enableScrollRef.current = undefined;\n }, []);\n\n const [position, count] = useModalOrder(!!visible && !isServerEnv, modalRef);\n const isOverlayHidden = (position === 0 && count > 0) || (count > 1 && position > 1);\n\n const { breakpoint } = useBreakpoint();\n useEffect(() => {\n if (!visible) {\n return;\n }\n\n const currentBreakpointVisible = !INVISIBLE_FOR_BREAKPOINTS.includes(breakpoint);\n if (!currentBreakpointVisible) {\n onExited();\n return;\n }\n\n onEntering();\n // visible не должно быть в зависимостях, т.к. этот эффект обрабатывает только изменение брейкпоинта\n // visible обрабатывается CSSTransition\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [breakpoint, onEntering, onExited]);\n\n useEffect(\n () => () => {\n enableScrollRef.current?.();\n enableScrollRef.current = undefined;\n },\n [visible]\n );\n\n useLayoutEffect(() => {\n const animationTimeoutElement = document.createElement('div');\n animationTimeoutElement.classList.add(styles.animationTimeout);\n document.body.appendChild(animationTimeoutElement);\n const style = window.getComputedStyle(animationTimeoutElement);\n setAnimationTimeout({\n enter: toNumber(style.getPropertyValue('--enter-animation-duration')),\n exit: toNumber(style.getPropertyValue('--exit-animation-duration')),\n });\n document.body.removeChild(animationTimeoutElement);\n }, [setAnimationTimeout]);\n\n if (INVISIBLE_FOR_BREAKPOINTS.includes(breakpoint) || isServerEnv) {\n return null;\n }\n\n const modalHeaderProps = {\n title,\n titleElement,\n titleAlignment,\n titleSize,\n titleMaxLines,\n titleDescription,\n titleDescriptionMaxLines,\n titleStyle,\n titleDescriptionStyle,\n headerImage,\n headerHeight,\n options,\n actions,\n actionLink,\n } as ModalHeaderProps;\n\n return createPortal(\n <CSSTransition\n in={visible && !isServerEnv}\n nodeRef={overlayRef}\n onEntering={onEntering}\n onExited={onExited}\n classNames={{\n enter: styles.modalAnimationEnter,\n enterActive: styles.modalAnimationEnterActive,\n exit: styles.modalAnimationExit,\n exitActive: styles.modalAnimationExitActive,\n }}\n timeout={animationTimeout}\n unmountOnExit\n >\n <Layer layer={InternalLayerName.Modal}>\n <div\n ref={overlayRef}\n className={styles.modalOverlay}\n style={isOverlayHidden ? { backgroundColor: 'transparent' } : {}}\n onKeyDown={(event) => {\n if (keyboardMatch(event.nativeEvent, keyboardKeys.Escape)) {\n onClose();\n }\n }}\n data-qa=\"modal-overlay\"\n >\n <div\n {...rest}\n {...additionalProps}\n role=\"dialog\"\n className={classnames(styles.modal, { [styles.modalSmall]: size === 'small' })}\n ref={modalRefCallback}\n tabIndex={0}\n >\n <ModalContentWithHeader {...modalHeaderProps} labelId={labelId}>\n {children}\n </ModalContentWithHeader>\n <ModalFooter leftButtons={leftButtons} rightButtons={rightButtons} />\n </div>\n </div>\n </Layer>\n </CSSTransition>,\n host || document.body\n );\n }\n);\n\nModal.displayName = 'Modal';\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useState, useRef, useLayoutEffect } from 'react';
|
|
4
|
+
import classnames from 'classnames';
|
|
5
|
+
import { requestAnimation } from '@hh.ru/magritte-common-func-utils';
|
|
6
|
+
import { Divider } from '@hh.ru/magritte-ui-divider';
|
|
7
|
+
import { ModalHeader } from './ModalHeader.js';
|
|
8
|
+
import { s as styles } from './modal-198e0f95.js';
|
|
9
|
+
import '@hh.ru/magritte-ui-title';
|
|
10
|
+
|
|
11
|
+
const checkIsScrolledToBottom = (el) => {
|
|
12
|
+
return Math.abs(el.scrollHeight - el.scrollTop - el.clientHeight) < 1;
|
|
13
|
+
};
|
|
14
|
+
const ModalContentWithHeader = ({ labelId, children, ...modalHeaderProps }) => {
|
|
15
|
+
const { title, headerImage, actions, actionLink, options } = modalHeaderProps;
|
|
16
|
+
const [isDividerVisible, setDividerVisible] = useState(false);
|
|
17
|
+
const [isTopDividerVisible, setTopDividerVisible] = useState(false);
|
|
18
|
+
const contentContainerRef = useRef(null);
|
|
19
|
+
const withoutHeader = !title && !headerImage && !actions && !actionLink && !options;
|
|
20
|
+
const onlyActions = !title && !headerImage && !options && (actions || actionLink);
|
|
21
|
+
const showTopDivider = isTopDividerVisible && (options || !headerImage) && !onlyActions && !withoutHeader;
|
|
22
|
+
useLayoutEffect(() => {
|
|
23
|
+
if (contentContainerRef.current) {
|
|
24
|
+
const observer = new ResizeObserver(requestAnimation(() => {
|
|
25
|
+
if (!contentContainerRef.current) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const isScrollable = contentContainerRef.current.scrollHeight > contentContainerRef.current.clientHeight;
|
|
29
|
+
const hasScroll = isScrollable && !checkIsScrolledToBottom(contentContainerRef.current);
|
|
30
|
+
setDividerVisible(hasScroll);
|
|
31
|
+
}));
|
|
32
|
+
observer.observe(contentContainerRef.current);
|
|
33
|
+
return () => observer.disconnect();
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}, [setDividerVisible]);
|
|
37
|
+
const handleScroll = () => {
|
|
38
|
+
if (!contentContainerRef.current) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
setTopDividerVisible(contentContainerRef.current.scrollTop !== 0);
|
|
42
|
+
setDividerVisible(!checkIsScrolledToBottom(contentContainerRef.current));
|
|
43
|
+
};
|
|
44
|
+
return (jsxs(Fragment, { children: [jsxs("div", { className: classnames(styles.modalContentWrapper, {
|
|
45
|
+
[styles.modalContentWrapperOneLine]: onlyActions,
|
|
46
|
+
}), children: [jsx(ModalHeader, { ...modalHeaderProps, labelId: labelId }), showTopDivider && (jsx("div", { className: styles.dividerContainer, children: jsx(Divider, {}) })), jsx("div", { className: classnames(styles.modalContent, {
|
|
47
|
+
[styles.modalContentWithDivider]: isTopDividerVisible && headerImage && !options,
|
|
48
|
+
}), ref: contentContainerRef, onScroll: handleScroll, children: children })] }), isDividerVisible && (jsx("div", { className: styles.dividerContainer, children: jsx(Divider, {}) }))] }));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { ModalContentWithHeader };
|
|
52
|
+
//# sourceMappingURL=ModalContentWithHeader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModalContentWithHeader.js","sources":["../src/ModalContentWithHeader.tsx"],"sourcesContent":["import { FC, PropsWithChildren, useLayoutEffect, useRef, useState } from 'react';\nimport classnames from 'classnames';\n\nimport { requestAnimation } from '@hh.ru/magritte-common-func-utils';\nimport { Divider } from '@hh.ru/magritte-ui-divider';\nimport { ModalHeader } from '@hh.ru/magritte-ui-modal/ModalHeader';\nimport { ModalHeaderProps } from '@hh.ru/magritte-ui-modal/types';\n\nimport styles from './modal.less';\n\nconst checkIsScrolledToBottom = (el: HTMLElement) => {\n return Math.abs(el.scrollHeight - el.scrollTop - el.clientHeight) < 1;\n};\n\nexport const ModalContentWithHeader: FC<PropsWithChildren<ModalHeaderProps & { labelId: string }>> = ({\n labelId,\n children,\n ...modalHeaderProps\n}) => {\n const { title, headerImage, actions, actionLink, options } = modalHeaderProps;\n const [isDividerVisible, setDividerVisible] = useState(false);\n const [isTopDividerVisible, setTopDividerVisible] = useState(false);\n const contentContainerRef = useRef<HTMLDivElement>(null);\n const withoutHeader = !title && !headerImage && !actions && !actionLink && !options;\n const onlyActions = !title && !headerImage && !options && (actions || actionLink);\n const showTopDivider = isTopDividerVisible && (options || !headerImage) && !onlyActions && !withoutHeader;\n\n useLayoutEffect(() => {\n if (contentContainerRef.current) {\n const observer = new ResizeObserver(\n requestAnimation(() => {\n if (!contentContainerRef.current) {\n return;\n }\n const isScrollable =\n contentContainerRef.current.scrollHeight > contentContainerRef.current.clientHeight;\n const hasScroll = isScrollable && !checkIsScrolledToBottom(contentContainerRef.current);\n setDividerVisible(hasScroll);\n })\n );\n observer.observe(contentContainerRef.current);\n return () => observer.disconnect();\n }\n\n return undefined;\n }, [setDividerVisible]);\n\n const handleScroll = () => {\n if (!contentContainerRef.current) {\n return;\n }\n setTopDividerVisible(contentContainerRef.current.scrollTop !== 0);\n setDividerVisible(!checkIsScrolledToBottom(contentContainerRef.current));\n };\n return (\n <>\n <div\n className={classnames(styles.modalContentWrapper, {\n [styles.modalContentWrapperOneLine]: onlyActions,\n })}\n >\n <ModalHeader {...modalHeaderProps} labelId={labelId} />\n {showTopDivider && (\n <div className={styles.dividerContainer}>\n <Divider />\n </div>\n )}\n <div\n className={classnames(styles.modalContent, {\n [styles.modalContentWithDivider]: isTopDividerVisible && headerImage && !options,\n })}\n ref={contentContainerRef}\n onScroll={handleScroll}\n >\n {children}\n </div>\n </div>\n {isDividerVisible && (\n <div className={styles.dividerContainer}>\n <Divider />\n </div>\n )}\n </>\n );\n};\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
|
package/ModalFooter.d.ts
ADDED
package/ModalFooter.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { s as styles } from './modal-198e0f95.js';
|
|
4
|
+
|
|
5
|
+
const ModalFooter = ({ leftButtons, rightButtons }) => {
|
|
6
|
+
if (!leftButtons && !rightButtons) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
return (jsxs("div", { className: styles.modalFooter, children: [jsx("div", { className: styles.modalButtonsContainer, children: leftButtons || null }), jsx("div", { className: styles.modalButtonsContainer, children: rightButtons || null })] }));
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export { ModalFooter };
|
|
13
|
+
//# sourceMappingURL=ModalFooter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModalFooter.js","sources":["../src/ModalFooter.tsx"],"sourcesContent":["import { FC } from 'react';\n\nimport { ModalFooterProps } from '@hh.ru/magritte-ui-modal/types';\n\nimport styles from './modal.less';\n\nexport const ModalFooter: FC<ModalFooterProps> = ({ leftButtons, rightButtons }) => {\n if (!leftButtons && !rightButtons) {\n return null;\n }\n\n return (\n <div className={styles.modalFooter}>\n <div className={styles.modalButtonsContainer}>{leftButtons || null}</div>\n <div className={styles.modalButtonsContainer}>{rightButtons || null}</div>\n </div>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":";;;AAMa,MAAA,WAAW,GAAyB,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,KAAI;AAC/E,IAAA,IAAI,CAAC,WAAW,IAAI,CAAC,YAAY,EAAE;AAC/B,QAAA,OAAO,IAAI,CAAC;AACf,KAAA;AAED,IAAA,QACIA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,WAAW,EAC9B,QAAA,EAAA,CAAAC,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,qBAAqB,EAAG,QAAA,EAAA,WAAW,IAAI,IAAI,EAAO,CAAA,EACzEA,GAAK,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,MAAM,CAAC,qBAAqB,EAAA,QAAA,EAAG,YAAY,IAAI,IAAI,EAAO,CAAA,CAAA,EAAA,CACxE,EACR;AACN;;;;"}
|
package/ModalHeader.d.ts
ADDED
package/ModalHeader.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import classnames from 'classnames';
|
|
4
|
+
import { Title } from '@hh.ru/magritte-ui-title';
|
|
5
|
+
|
|
6
|
+
var styles = {"wrapper":"magritte-wrapper___zH8vB_3-0-14","content":"magritte-content___o6ktq_3-0-14","options":"magritte-options___qfErQ_3-0-14","content-with-image":"magritte-content-with-image___YarBO_3-0-14","contentWithImage":"magritte-content-with-image___YarBO_3-0-14","actions":"magritte-actions___nQILV_3-0-14","actions-with-link":"magritte-actions-with-link___hnDux_3-0-14","actionsWithLink":"magritte-actions-with-link___hnDux_3-0-14","actions-single":"magritte-actions-single___usfKu_3-0-14","actionsSingle":"magritte-actions-single___usfKu_3-0-14"};
|
|
7
|
+
|
|
8
|
+
const ModalHeader = ({ title, headerImage, headerHeight = 0, titleAlignment, titleElement, titleMaxLines, titleSize, titleDescription, titleDescriptionMaxLines, titleStyle, titleDescriptionStyle, options, actions: _actions, actionLink, labelId, }) => {
|
|
9
|
+
const actions = Array.isArray(_actions) ? _actions.slice(0, 5) : _actions;
|
|
10
|
+
if (!title && !headerImage && !actions && !actionLink && !options) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const withActions = !!actions || !!actionLink;
|
|
14
|
+
const minHeight = headerImage ? Math.max(headerHeight, 200) : 0;
|
|
15
|
+
const currentTitleStyle = titleStyle || (headerImage ? 'contrast' : 'primary');
|
|
16
|
+
const currentTitleDescriptionStyle = titleDescriptionStyle || (headerImage ? 'contrast' : 'primary');
|
|
17
|
+
const withContent = title || headerImage || actionLink || actions;
|
|
18
|
+
return (jsxs("div", { "data-qa": "modal-header", className: styles.wrapper, children: [withContent && (jsxs("div", { className: classnames(styles.content, {
|
|
19
|
+
[styles.contentWithImage]: !!headerImage,
|
|
20
|
+
}), "data-qa": "modal-header-image", style: {
|
|
21
|
+
backgroundImage: headerImage
|
|
22
|
+
? `${title ? 'var(--modal-header-gradient), ' : ''}url(${headerImage})`
|
|
23
|
+
: 'none',
|
|
24
|
+
minHeight,
|
|
25
|
+
}, children: [jsx(Title, { id: labelId, Element: titleElement, alignment: titleAlignment, maxLines: titleMaxLines, size: titleSize, style: currentTitleStyle, description: titleDescription, descriptionMaxLines: titleDescriptionMaxLines, descriptionStyle: currentTitleDescriptionStyle, children: title }), withActions && (jsx("div", { className: classnames(styles.actions, {
|
|
26
|
+
[styles.actionsWithLink]: !actions && !!actionLink,
|
|
27
|
+
[styles.actionsSingle]: Array.isArray(actions) ? actions.length === 1 : !!actions,
|
|
28
|
+
}), children: actions || actionLink }))] })), options && jsx("div", { className: styles.options, children: options })] }));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { ModalHeader };
|
|
32
|
+
//# sourceMappingURL=ModalHeader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModalHeader.js","sources":["../src/ModalHeader.tsx"],"sourcesContent":["import { FC } from 'react';\nimport classnames from 'classnames';\n\nimport { ModalHeaderProps } from '@hh.ru/magritte-ui-modal/types';\nimport { Title } from '@hh.ru/magritte-ui-title';\n\nimport styles from './modal-header.less';\n\nexport const ModalHeader: FC<ModalHeaderProps & { labelId: string }> = ({\n title,\n headerImage,\n headerHeight = 0,\n titleAlignment,\n titleElement,\n titleMaxLines,\n titleSize,\n titleDescription,\n titleDescriptionMaxLines,\n titleStyle,\n titleDescriptionStyle,\n options,\n actions: _actions,\n actionLink,\n labelId,\n}) => {\n const actions = Array.isArray(_actions) ? _actions.slice(0, 5) : _actions;\n if (!title && !headerImage && !actions && !actionLink && !options) {\n return null;\n }\n const withActions = !!actions || !!actionLink;\n const minHeight = headerImage ? Math.max(headerHeight, 200) : 0;\n const currentTitleStyle = titleStyle || (headerImage ? 'contrast' : 'primary');\n const currentTitleDescriptionStyle = titleDescriptionStyle || (headerImage ? 'contrast' : 'primary');\n const withContent = title || headerImage || actionLink || actions;\n\n return (\n <div data-qa=\"modal-header\" className={styles.wrapper}>\n {withContent && (\n <div\n className={classnames(styles.content, {\n [styles.contentWithImage]: !!headerImage,\n })}\n data-qa=\"modal-header-image\"\n style={{\n backgroundImage: headerImage\n ? `${title ? 'var(--modal-header-gradient), ' : ''}url(${headerImage})`\n : 'none',\n minHeight,\n }}\n >\n <Title\n id={labelId}\n Element={titleElement}\n alignment={titleAlignment}\n maxLines={titleMaxLines}\n size={titleSize}\n style={currentTitleStyle}\n description={titleDescription}\n descriptionMaxLines={titleDescriptionMaxLines}\n descriptionStyle={currentTitleDescriptionStyle}\n >\n {title}\n </Title>\n {withActions && (\n <div\n className={classnames(styles.actions, {\n [styles.actionsWithLink]: !actions && !!actionLink,\n [styles.actionsSingle]: Array.isArray(actions) ? actions.length === 1 : !!actions,\n })}\n >\n {actions || actionLink}\n </div>\n )}\n </div>\n )}\n {options && <div className={styles.options}>{options}</div>}\n </div>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":";;;;;;AAQa,MAAA,WAAW,GAA+C,CAAC,EACpE,KAAK,EACL,WAAW,EACX,YAAY,GAAG,CAAC,EAChB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,wBAAwB,EACxB,UAAU,EACV,qBAAqB,EACrB,OAAO,EACP,OAAO,EAAE,QAAQ,EACjB,UAAU,EACV,OAAO,GACV,KAAI;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC;AAC1E,IAAA,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,IAAI,CAAC,OAAO,EAAE;AAC/D,QAAA,OAAO,IAAI,CAAC;AACf,KAAA;IACD,MAAM,WAAW,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,UAAU,CAAC;AAC9C,IAAA,MAAM,SAAS,GAAG,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AAChE,IAAA,MAAM,iBAAiB,GAAG,UAAU,KAAK,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC,CAAC;AAC/E,IAAA,MAAM,4BAA4B,GAAG,qBAAqB,KAAK,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC,CAAC;IACrG,MAAM,WAAW,GAAG,KAAK,IAAI,WAAW,IAAI,UAAU,IAAI,OAAO,CAAC;IAElE,QACIA,yBAAa,cAAc,EAAC,SAAS,EAAE,MAAM,CAAC,OAAO,EAAA,QAAA,EAAA,CAChD,WAAW,KACRA,cACI,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE;AAClC,oBAAA,CAAC,MAAM,CAAC,gBAAgB,GAAG,CAAC,CAAC,WAAW;AAC3C,iBAAA,CAAC,EACM,SAAA,EAAA,oBAAoB,EAC5B,KAAK,EAAE;AACH,oBAAA,eAAe,EAAE,WAAW;AACxB,0BAAE,CAAA,EAAG,KAAK,GAAG,gCAAgC,GAAG,EAAE,CAAA,IAAA,EAAO,WAAW,CAAG,CAAA,CAAA;AACvE,0BAAE,MAAM;oBACZ,SAAS;iBACZ,EAED,QAAA,EAAA,CAAAC,GAAA,CAAC,KAAK,EAAA,EACF,EAAE,EAAE,OAAO,EACX,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,cAAc,EACzB,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,iBAAiB,EACxB,WAAW,EAAE,gBAAgB,EAC7B,mBAAmB,EAAE,wBAAwB,EAC7C,gBAAgB,EAAE,4BAA4B,EAE7C,QAAA,EAAA,KAAK,GACF,EACP,WAAW,KACRA,GACI,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE;4BAClC,CAAC,MAAM,CAAC,eAAe,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,UAAU;4BAClD,CAAC,MAAM,CAAC,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO;yBACpF,CAAC,EAAA,QAAA,EAED,OAAO,IAAI,UAAU,GACpB,CACT,CAAA,EAAA,CACC,CACT,EACA,OAAO,IAAIA,aAAK,SAAS,EAAE,MAAM,CAAC,OAAO,YAAG,OAAO,EAAA,CAAO,CACzD,EAAA,CAAA,EACR;AACN;;;;"}
|
package/index.css
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
:root{
|
|
2
|
+
--magritte-color-component-modal-background-action-v18-1-1:#20262b99;
|
|
3
|
+
--magritte-gradient-component-modal-background-fade-v18-1-1:linear-gradient(180deg, #00000000 0%, #0000007a 100%);
|
|
4
|
+
}
|
|
5
|
+
:root{
|
|
6
|
+
--magritte-static-border-radius-300-v18-1-1:12px;
|
|
7
|
+
--magritte-static-border-radius-600-v18-1-1:24px;
|
|
8
|
+
}
|
|
9
|
+
.magritte-night-theme{
|
|
10
|
+
--magritte-color-component-modal-background-action-v18-1-1:#20262b99;
|
|
11
|
+
--magritte-gradient-component-modal-background-fade-v18-1-1:linear-gradient(180deg, #00000000 0%, #0000007a 100%);
|
|
12
|
+
}
|
|
13
|
+
.magritte-wrapper___zH8vB_3-0-14{
|
|
14
|
+
margin-bottom:32px;
|
|
15
|
+
}
|
|
16
|
+
.magritte-content___o6ktq_3-0-14{
|
|
17
|
+
display:flex;
|
|
18
|
+
align-items:flex-start;
|
|
19
|
+
}
|
|
20
|
+
.magritte-content___o6ktq_3-0-14 + .magritte-options___qfErQ_3-0-14{
|
|
21
|
+
margin-top:24px;
|
|
22
|
+
}
|
|
23
|
+
.magritte-content___o6ktq_3-0-14.magritte-content-with-image___YarBO_3-0-14 + .magritte-options___qfErQ_3-0-14{
|
|
24
|
+
margin-top:32px;
|
|
25
|
+
}
|
|
26
|
+
.magritte-actions___nQILV_3-0-14{
|
|
27
|
+
display:flex;
|
|
28
|
+
padding-left:16px;
|
|
29
|
+
gap:4px;
|
|
30
|
+
margin-left:auto;
|
|
31
|
+
--magritte-ui-link-padding-override:9px;
|
|
32
|
+
}
|
|
33
|
+
.magritte-actions-with-link___hnDux_3-0-14{
|
|
34
|
+
padding:0 8px 0 28px;
|
|
35
|
+
}
|
|
36
|
+
.magritte-content-with-image___YarBO_3-0-14{
|
|
37
|
+
flex-direction:column;
|
|
38
|
+
justify-content:flex-end;
|
|
39
|
+
margin:-20px -20px 0;
|
|
40
|
+
background-size:cover;
|
|
41
|
+
--modal-header-gradient:var(--magritte-gradient-component-modal-background-fade-v18-1-1);
|
|
42
|
+
border-radius:var(--magritte-static-border-radius-600-v18-1-1);
|
|
43
|
+
padding:12px 24px 24px;
|
|
44
|
+
box-sizing:border-box;
|
|
45
|
+
}
|
|
46
|
+
.magritte-content-with-image___YarBO_3-0-14 .magritte-actions___nQILV_3-0-14{
|
|
47
|
+
order:-1;
|
|
48
|
+
gap:0;
|
|
49
|
+
margin-right:-12px;
|
|
50
|
+
margin-bottom:auto;
|
|
51
|
+
}
|
|
52
|
+
.magritte-content-with-image___YarBO_3-0-14 .magritte-actions___nQILV_3-0-14:not(.magritte-actions-with-link___hnDux_3-0-14){
|
|
53
|
+
padding:0 4px;
|
|
54
|
+
background-color:var(--magritte-color-component-modal-background-action-v18-1-1);
|
|
55
|
+
border-radius:var(--magritte-static-border-radius-300-v18-1-1);
|
|
56
|
+
}
|
|
57
|
+
.magritte-content-with-image___YarBO_3-0-14 .magritte-actions___nQILV_3-0-14.magritte-actions-single___usfKu_3-0-14:not(.magritte-actions-with-link___hnDux_3-0-14){
|
|
58
|
+
padding:0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
:root{
|
|
62
|
+
--magritte-color-background-overlay-v18-1-1:#20262b99;
|
|
63
|
+
--magritte-color-component-modal-background-content-v18-1-1:#ffffff;
|
|
64
|
+
}
|
|
65
|
+
:root{
|
|
66
|
+
--magritte-semantic-animation-ease-in-out-200-timing-function-v18-1-1:cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
67
|
+
--magritte-semantic-animation-ease-in-out-200-duration-v18-1-1:200ms;
|
|
68
|
+
--magritte-semantic-animation-ease-in-out-300-timing-function-v18-1-1:cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
69
|
+
--magritte-semantic-animation-ease-in-out-300-duration-v18-1-1:300ms;
|
|
70
|
+
--magritte-static-border-radius-800-v18-1-1:32px;
|
|
71
|
+
}
|
|
72
|
+
.magritte-night-theme{
|
|
73
|
+
--magritte-color-background-overlay-v18-1-1:#20262b99;
|
|
74
|
+
--magritte-color-component-modal-background-content-v18-1-1:#1B1B1B;
|
|
75
|
+
}
|
|
76
|
+
.magritte-modal-overlay___lK22l_3-0-14{
|
|
77
|
+
position:fixed;
|
|
78
|
+
top:0;
|
|
79
|
+
right:0;
|
|
80
|
+
bottom:0;
|
|
81
|
+
left:0;
|
|
82
|
+
display:flex;
|
|
83
|
+
align-items:center;
|
|
84
|
+
justify-content:center;
|
|
85
|
+
background-color:var(--magritte-color-background-overlay-v18-1-1);
|
|
86
|
+
z-index:1;
|
|
87
|
+
user-select:text;
|
|
88
|
+
}
|
|
89
|
+
.magritte-modal___RAW6S_3-0-14{
|
|
90
|
+
display:flex;
|
|
91
|
+
box-sizing:border-box;
|
|
92
|
+
width:720px;
|
|
93
|
+
margin:0 20px;
|
|
94
|
+
padding:32px;
|
|
95
|
+
flex-direction:column;
|
|
96
|
+
max-height:calc(100vh - 96px * 2);
|
|
97
|
+
position:relative;
|
|
98
|
+
background-color:var(--magritte-color-component-modal-background-content-v18-1-1);
|
|
99
|
+
border-radius:var(--magritte-static-border-radius-800-v18-1-1);
|
|
100
|
+
overflow:hidden;
|
|
101
|
+
}
|
|
102
|
+
.magritte-modal-small___MMQT4_3-0-14{
|
|
103
|
+
width:460px;
|
|
104
|
+
}
|
|
105
|
+
.magritte-modal-content___46QFS_3-0-14{
|
|
106
|
+
flex:1 1;
|
|
107
|
+
overflow-y:auto;
|
|
108
|
+
padding:0 5px;
|
|
109
|
+
margin:0 -5px;
|
|
110
|
+
overscroll-behavior:none;
|
|
111
|
+
}
|
|
112
|
+
.magritte-modal-content__with-divider___an3I5_3-0-14{
|
|
113
|
+
margin-top:-16px;
|
|
114
|
+
}
|
|
115
|
+
.magritte-modal-content-wrapper___23XFT_3-0-14{
|
|
116
|
+
display:flex;
|
|
117
|
+
flex-direction:column;
|
|
118
|
+
min-height:0;
|
|
119
|
+
flex:1 1;
|
|
120
|
+
}
|
|
121
|
+
.magritte-modal-content-wrapper__one-line___tYg8d_3-0-14{
|
|
122
|
+
flex-direction:row-reverse;
|
|
123
|
+
}
|
|
124
|
+
.magritte-divider-container___qP3VK_3-0-14{
|
|
125
|
+
margin:0 -32px;
|
|
126
|
+
}
|
|
127
|
+
.magritte-modal-footer___8xPqQ_3-0-14{
|
|
128
|
+
flex:0 0;
|
|
129
|
+
padding-top:32px;
|
|
130
|
+
display:flex;
|
|
131
|
+
justify-content:space-between;
|
|
132
|
+
}
|
|
133
|
+
.magritte-modal-buttons-container___1O1Nr_3-0-14{
|
|
134
|
+
display:flex;
|
|
135
|
+
gap:12px;
|
|
136
|
+
}
|
|
137
|
+
.magritte-animation-timeout___w-j7K_3-0-14,
|
|
138
|
+
.magritte-modal-animation-enter-active___E8KLu_3-0-14,
|
|
139
|
+
.magritte-modal-animation-exit-active___ERjKa_3-0-14{
|
|
140
|
+
--enter-animation-duration:0;
|
|
141
|
+
--exit-animation-duration:0;
|
|
142
|
+
}
|
|
143
|
+
@media (prefers-reduced-motion: no-preference){
|
|
144
|
+
.magritte-animation-timeout___w-j7K_3-0-14,
|
|
145
|
+
.magritte-modal-animation-enter-active___E8KLu_3-0-14,
|
|
146
|
+
.magritte-modal-animation-exit-active___ERjKa_3-0-14{
|
|
147
|
+
--enter-animation-duration:var(--magritte-semantic-animation-ease-in-out-300-duration-v18-1-1);
|
|
148
|
+
--exit-animation-duration:var(--magritte-semantic-animation-ease-in-out-200-duration-v18-1-1);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
.magritte-modal-animation-enter___kruLO_3-0-14.magritte-modal-overlay___lK22l_3-0-14{
|
|
152
|
+
opacity:0;
|
|
153
|
+
}
|
|
154
|
+
.magritte-modal-animation-enter___kruLO_3-0-14 .magritte-modal___RAW6S_3-0-14{
|
|
155
|
+
opacity:0;
|
|
156
|
+
transform:scale(0.96);
|
|
157
|
+
}
|
|
158
|
+
.magritte-modal-animation-enter-active___E8KLu_3-0-14 .magritte-modal___RAW6S_3-0-14,
|
|
159
|
+
.magritte-modal-animation-enter-active___E8KLu_3-0-14.magritte-modal-overlay___lK22l_3-0-14{
|
|
160
|
+
opacity:1;
|
|
161
|
+
transform:scale(1);
|
|
162
|
+
transition-property:opacity, transform;
|
|
163
|
+
transition-duration:var(--enter-animation-duration);
|
|
164
|
+
transition-timing-function:var(--magritte-semantic-animation-ease-in-out-300-timing-function-v18-1-1);
|
|
165
|
+
}
|
|
166
|
+
.magritte-modal-animation-exit___0jNgl_3-0-14.magritte-modal-overlay___lK22l_3-0-14{
|
|
167
|
+
opacity:1;
|
|
168
|
+
}
|
|
169
|
+
.magritte-modal-animation-exit___0jNgl_3-0-14 .magritte-modal___RAW6S_3-0-14{
|
|
170
|
+
opacity:1;
|
|
171
|
+
transform:scale(1);
|
|
172
|
+
}
|
|
173
|
+
.magritte-modal-animation-exit-active___ERjKa_3-0-14.magritte-modal-overlay___lK22l_3-0-14{
|
|
174
|
+
opacity:0;
|
|
175
|
+
}
|
|
176
|
+
.magritte-modal-animation-exit-active___ERjKa_3-0-14 .magritte-modal___RAW6S_3-0-14{
|
|
177
|
+
opacity:0;
|
|
178
|
+
transform:scale(0.96);
|
|
179
|
+
}
|
|
180
|
+
.magritte-modal-animation-exit-active___ERjKa_3-0-14 .magritte-modal___RAW6S_3-0-14,
|
|
181
|
+
.magritte-modal-animation-exit-active___ERjKa_3-0-14.magritte-modal-overlay___lK22l_3-0-14{
|
|
182
|
+
transition-property:opacity, transform;
|
|
183
|
+
transition-duration:var(--exit-animation-duration);
|
|
184
|
+
transition-timing-function:var(--magritte-semantic-animation-ease-in-out-200-timing-function-v18-1-1);
|
|
185
|
+
}
|
package/index.d.ts
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
export * from '@hh.ru/magritte-ui-theme-provider';
|
|
3
|
+
export { Modal } from './Modal.js';
|
|
4
|
+
import 'react/jsx-runtime';
|
|
5
|
+
import 'react';
|
|
6
|
+
import 'react-dom';
|
|
7
|
+
import 'react-transition-group';
|
|
8
|
+
import 'classnames';
|
|
9
|
+
import '@hh.ru/magritte-common-is-server-env';
|
|
10
|
+
import '@hh.ru/magritte-common-keyboard';
|
|
11
|
+
import '@hh.ru/magritte-common-modal-helper';
|
|
12
|
+
import '@hh.ru/magritte-common-use-multiple-refs';
|
|
13
|
+
import '@hh.ru/magritte-internal-layer-name';
|
|
14
|
+
import '@hh.ru/magritte-ui-breakpoint';
|
|
15
|
+
import '@hh.ru/magritte-ui-layer';
|
|
16
|
+
import './ModalContentWithHeader.js';
|
|
17
|
+
import '@hh.ru/magritte-common-func-utils';
|
|
18
|
+
import '@hh.ru/magritte-ui-divider';
|
|
19
|
+
import './ModalHeader.js';
|
|
20
|
+
import '@hh.ru/magritte-ui-title';
|
|
21
|
+
import './modal-198e0f95.js';
|
|
22
|
+
import './ModalFooter.js';
|
|
23
|
+
import './useModalOrder.js';
|
|
24
|
+
import '@hh.ru/magritte-common-dom-storage';
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;"}
|
package/index.mock.d.ts
ADDED
package/index.mock.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import { mockComponent } from '@hh.ru/magritte-ui-mock-component';
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
5
|
+
const { ThemeProvider } = jest.requireActual('@hh.ru/magritte-ui-theme-provider/index');
|
|
6
|
+
const Modal = mockComponent('Modal', undefined, {
|
|
7
|
+
withChildren: true,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export { Modal, ThemeProvider };
|
|
11
|
+
//# sourceMappingURL=index.mock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mock.js","sources":["../src/index.mock.ts"],"sourcesContent":["import { ForwardRefExoticComponent } from 'react';\n\nimport { mockComponent } from '@hh.ru/magritte-ui-mock-component';\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\nconst { ThemeProvider } = jest.requireActual('@hh.ru/magritte-ui-theme-provider/index');\n\nexport { ThemeProvider };\n\nexport const Modal: ForwardRefExoticComponent<Record<string, unknown>> = mockComponent('Modal', undefined, {\n withChildren: true,\n});\n"],"names":[],"mappings":";;AAIA;AACM,MAAA,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,yCAAyC,EAAE;MAI3E,KAAK,GAAuD,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE;AACvG,IAAA,YAAY,EAAE,IAAI;AACrB,CAAA;;;;"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
var styles = {"modal-overlay":"magritte-modal-overlay___lK22l_3-0-14","modalOverlay":"magritte-modal-overlay___lK22l_3-0-14","modal":"magritte-modal___RAW6S_3-0-14","modal-small":"magritte-modal-small___MMQT4_3-0-14","modalSmall":"magritte-modal-small___MMQT4_3-0-14","modal-content":"magritte-modal-content___46QFS_3-0-14","modalContent":"magritte-modal-content___46QFS_3-0-14","modal-content__with-divider":"magritte-modal-content__with-divider___an3I5_3-0-14","modalContentWithDivider":"magritte-modal-content__with-divider___an3I5_3-0-14","modal-content-wrapper":"magritte-modal-content-wrapper___23XFT_3-0-14","modalContentWrapper":"magritte-modal-content-wrapper___23XFT_3-0-14","modal-content-wrapper__one-line":"magritte-modal-content-wrapper__one-line___tYg8d_3-0-14","modalContentWrapperOneLine":"magritte-modal-content-wrapper__one-line___tYg8d_3-0-14","divider-container":"magritte-divider-container___qP3VK_3-0-14","dividerContainer":"magritte-divider-container___qP3VK_3-0-14","modal-footer":"magritte-modal-footer___8xPqQ_3-0-14","modalFooter":"magritte-modal-footer___8xPqQ_3-0-14","modal-buttons-container":"magritte-modal-buttons-container___1O1Nr_3-0-14","modalButtonsContainer":"magritte-modal-buttons-container___1O1Nr_3-0-14","animation-timeout":"magritte-animation-timeout___w-j7K_3-0-14","animationTimeout":"magritte-animation-timeout___w-j7K_3-0-14","modal-animation-enter-active":"magritte-modal-animation-enter-active___E8KLu_3-0-14","modalAnimationEnterActive":"magritte-modal-animation-enter-active___E8KLu_3-0-14","modal-animation-exit-active":"magritte-modal-animation-exit-active___ERjKa_3-0-14","modalAnimationExitActive":"magritte-modal-animation-exit-active___ERjKa_3-0-14","modal-animation-enter":"magritte-modal-animation-enter___kruLO_3-0-14","modalAnimationEnter":"magritte-modal-animation-enter___kruLO_3-0-14","modal-animation-exit":"magritte-modal-animation-exit___0jNgl_3-0-14","modalAnimationExit":"magritte-modal-animation-exit___0jNgl_3-0-14"};
|
|
3
|
+
|
|
4
|
+
export { styles as s };
|
|
5
|
+
//# sourceMappingURL=modal-198e0f95.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal-198e0f95.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hh.ru/magritte-ui-modal",
|
|
3
|
+
"version": "3.0.14",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"types": "index.d.ts",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"index.css"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "yarn root:build $(pwd)",
|
|
11
|
+
"build-test-branch": "yarn root:build-test-branch $(pwd)",
|
|
12
|
+
"changelog": "yarn root:changelog $(pwd)",
|
|
13
|
+
"prepack": "yarn root:prepack $(pwd)",
|
|
14
|
+
"postpublish": "yarn root:postpublish $(pwd)",
|
|
15
|
+
"stylelint-test": "yarn root:stylelint-test $(pwd)",
|
|
16
|
+
"eslint-test": "yarn root:eslint-test $(pwd)",
|
|
17
|
+
"ts-config": "yarn root:ts-config $(pwd)",
|
|
18
|
+
"ts-check": "yarn root:ts-check $(pwd)",
|
|
19
|
+
"test": "yarn root:test $(pwd)"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@hh.ru/magritte-common-dom-storage": "1.0.5",
|
|
23
|
+
"@hh.ru/magritte-common-func-utils": "1.3.6",
|
|
24
|
+
"@hh.ru/magritte-common-is-server-env": "1.0.4",
|
|
25
|
+
"@hh.ru/magritte-common-keyboard": "3.0.2",
|
|
26
|
+
"@hh.ru/magritte-common-modal-helper": "1.2.5",
|
|
27
|
+
"@hh.ru/magritte-common-use-multiple-refs": "1.1.2",
|
|
28
|
+
"@hh.ru/magritte-design-tokens": "18.1.1",
|
|
29
|
+
"@hh.ru/magritte-internal-layer-name": "2.1.1",
|
|
30
|
+
"@hh.ru/magritte-ui-action": "4.3.3",
|
|
31
|
+
"@hh.ru/magritte-ui-breakpoint": "4.0.1",
|
|
32
|
+
"@hh.ru/magritte-ui-divider": "1.1.24",
|
|
33
|
+
"@hh.ru/magritte-ui-icon": "7.1.3",
|
|
34
|
+
"@hh.ru/magritte-ui-layer": "2.0.3",
|
|
35
|
+
"@hh.ru/magritte-ui-mock-component": "1.0.10",
|
|
36
|
+
"@hh.ru/magritte-ui-theme-provider": "1.1.21",
|
|
37
|
+
"@hh.ru/magritte-ui-title": "3.0.8"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"classnames": ">=2.3.2",
|
|
41
|
+
"react": ">=18.2.0",
|
|
42
|
+
"react-dom": ">=18.2.0",
|
|
43
|
+
"react-transition-group": ">=4.4.5"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"gitHead": "b660dd64fca3eaad5ec44ea9a73f92bb0d9694aa"
|
|
49
|
+
}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ReactNode, PropsWithChildren } from 'react';
|
|
2
|
+
import { TitleProps } from '@hh.ru/magritte-ui-title';
|
|
3
|
+
type MakeNever<T> = {
|
|
4
|
+
[key in keyof T]?: never;
|
|
5
|
+
};
|
|
6
|
+
type ModalHeaderWithImage = {
|
|
7
|
+
/** URL изображение для фона заголовка */
|
|
8
|
+
headerImage: string;
|
|
9
|
+
/** Высота заголовка в пикселях, может указываться только если указан headerImage */
|
|
10
|
+
headerHeight?: number;
|
|
11
|
+
};
|
|
12
|
+
type ModalHeaderBaseProps = {
|
|
13
|
+
/** Текст заголовка */
|
|
14
|
+
title: TitleProps['children'];
|
|
15
|
+
/** Размер заголовка */
|
|
16
|
+
titleSize?: TitleProps['size'];
|
|
17
|
+
/** Выравнивание заголовка */
|
|
18
|
+
titleAlignment?: TitleProps['alignment'];
|
|
19
|
+
/** Максимальное кол-во строк перед обрезкой содержимого описания многоточием */
|
|
20
|
+
titleMaxLines?: TitleProps['maxLines'];
|
|
21
|
+
/** Элемент используемый для заголовка */
|
|
22
|
+
titleElement?: TitleProps['Element'];
|
|
23
|
+
/** Текст подзаголовка */
|
|
24
|
+
titleDescription?: TitleProps['description'];
|
|
25
|
+
/** Максимальное кол-во строк перед обрезкой содержимого описания многоточием */
|
|
26
|
+
titleDescriptionMaxLines?: TitleProps['descriptionMaxLines'];
|
|
27
|
+
/** Цвет заголовка */
|
|
28
|
+
titleStyle?: TitleProps['style'];
|
|
29
|
+
titleDescriptionStyle?: TitleProps['descriptionStyle'];
|
|
30
|
+
};
|
|
31
|
+
type ModalHeaderAdditionalProps = {
|
|
32
|
+
/** Опциональный контент внизу хедера */
|
|
33
|
+
options?: ReactNode;
|
|
34
|
+
/** набор Action-ов внутри хедера */
|
|
35
|
+
actions?: ReactNode | ReactNode[];
|
|
36
|
+
/** Link внутри хедера */
|
|
37
|
+
actionLink?: ReactNode;
|
|
38
|
+
};
|
|
39
|
+
export type ModalHeaderProps = (ModalHeaderBaseProps | MakeNever<ModalHeaderBaseProps>) & (ModalHeaderWithImage | MakeNever<ModalHeaderWithImage>) & ModalHeaderAdditionalProps;
|
|
40
|
+
export interface ModalFooterProps {
|
|
41
|
+
/** Кнопки отображаемые в левой части блока кнопок */
|
|
42
|
+
leftButtons?: ReactNode;
|
|
43
|
+
/** Кнопки отображаемые в правой части блока кнопок */
|
|
44
|
+
rightButtons?: ReactNode;
|
|
45
|
+
}
|
|
46
|
+
export interface ModalBaseProps extends PropsWithChildren {
|
|
47
|
+
/** Обработчик нажатия на кнопку закрытия */
|
|
48
|
+
onClose?: () => void;
|
|
49
|
+
/** Флаг управляющий видимостью модала */
|
|
50
|
+
visible?: boolean;
|
|
51
|
+
/** Размер */
|
|
52
|
+
size?: 'medium' | 'small';
|
|
53
|
+
/** Хост для отрисовки модала */
|
|
54
|
+
host?: HTMLElement;
|
|
55
|
+
}
|
|
56
|
+
export type ModalProps = ModalBaseProps & ModalHeaderProps & ModalFooterProps;
|
|
57
|
+
export {};
|
package/types.js
ADDED
package/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/useModalOrder.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import { useState, useLayoutEffect, useEffect } from 'react';
|
|
3
|
+
import { useDomStoredUniqueId, getValueFromDom, storeValueInDom } from '@hh.ru/magritte-common-dom-storage';
|
|
4
|
+
|
|
5
|
+
const STORAGE_NAME = '_MAGRITTE_MODAL_COUNTER_';
|
|
6
|
+
const getState = () => {
|
|
7
|
+
const state = getValueFromDom(STORAGE_NAME);
|
|
8
|
+
if (state === undefined) {
|
|
9
|
+
return {
|
|
10
|
+
prevVisiblility: {},
|
|
11
|
+
positions: {},
|
|
12
|
+
subscribers: {},
|
|
13
|
+
count: 0,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return state;
|
|
17
|
+
};
|
|
18
|
+
const storeState = (state) => {
|
|
19
|
+
storeValueInDom(STORAGE_NAME, state);
|
|
20
|
+
};
|
|
21
|
+
const counterFactory = () => {
|
|
22
|
+
return {
|
|
23
|
+
updateVisiblility: (id, visible) => {
|
|
24
|
+
// eslint-disable-next-line prefer-const
|
|
25
|
+
const state = getState();
|
|
26
|
+
const prevVisible = !!state.prevVisiblility[id];
|
|
27
|
+
if (visible === prevVisible) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
state.prevVisiblility[id] = visible;
|
|
31
|
+
if (visible) {
|
|
32
|
+
state.count += 1;
|
|
33
|
+
state.positions[id] = state.count;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
state.count -= 1;
|
|
37
|
+
const currentPosition = state.positions[id];
|
|
38
|
+
state.positions[id] = 0;
|
|
39
|
+
Object.entries(state.positions).forEach(([key, value]) => {
|
|
40
|
+
state.positions[key] = value > currentPosition ? value - 1 : value;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
storeState(state);
|
|
44
|
+
},
|
|
45
|
+
subscribe: (id, callback) => {
|
|
46
|
+
const state = getState();
|
|
47
|
+
state.subscribers[id] = callback;
|
|
48
|
+
storeState(state);
|
|
49
|
+
},
|
|
50
|
+
unsubscribe: (id) => {
|
|
51
|
+
const state = getState();
|
|
52
|
+
delete state.subscribers[id];
|
|
53
|
+
storeState(state);
|
|
54
|
+
},
|
|
55
|
+
notifyAll: () => {
|
|
56
|
+
const { subscribers, count, positions } = getState();
|
|
57
|
+
Object.entries(subscribers).forEach(([id, callback]) => callback({ position: positions[id], count }));
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
const counter = counterFactory();
|
|
62
|
+
const useModalOrder = (visible, modalRef) => {
|
|
63
|
+
const [position, setPosition] = useState({ position: 0, count: 0 });
|
|
64
|
+
const id = useDomStoredUniqueId();
|
|
65
|
+
useLayoutEffect(() => {
|
|
66
|
+
counter.updateVisiblility(id, visible);
|
|
67
|
+
counter.notifyAll();
|
|
68
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
69
|
+
}, [visible]);
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
counter.subscribe(id, setPosition);
|
|
72
|
+
counter.updateVisiblility(id, visible);
|
|
73
|
+
return () => {
|
|
74
|
+
counter.unsubscribe(id);
|
|
75
|
+
counter.updateVisiblility(id, false);
|
|
76
|
+
counter.notifyAll();
|
|
77
|
+
};
|
|
78
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
79
|
+
}, [id]);
|
|
80
|
+
useLayoutEffect(() => {
|
|
81
|
+
// Если это самый "верхний" модал передаем туда фокус
|
|
82
|
+
if (position.position === position.count && position.count > 0) {
|
|
83
|
+
modalRef.current?.focus();
|
|
84
|
+
}
|
|
85
|
+
}, [position, modalRef]);
|
|
86
|
+
return [position.position, position.count];
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export { useModalOrder };
|
|
90
|
+
//# sourceMappingURL=useModalOrder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useModalOrder.js","sources":["../src/useModalOrder.ts"],"sourcesContent":["import { RefObject, useEffect, useLayoutEffect, useState } from 'react';\n\nimport { storeValueInDom, getValueFromDom, useDomStoredUniqueId } from '@hh.ru/magritte-common-dom-storage';\n\ntype NotifyCallbackArg = { position: number; count: number };\n\ntype Subscribers = Record<string, (position: NotifyCallbackArg) => void>;\ntype VisibilityMap = Record<string, boolean>;\ntype PositionMap = Record<string, number>;\n\ntype ModalCounterState = {\n prevVisiblility: VisibilityMap;\n positions: PositionMap;\n subscribers: Subscribers;\n count: number;\n};\n\nconst STORAGE_NAME = '_MAGRITTE_MODAL_COUNTER_';\n\nconst getState = (): ModalCounterState => {\n const state = getValueFromDom<ModalCounterState>(STORAGE_NAME);\n if (state === undefined) {\n return {\n prevVisiblility: {},\n positions: {},\n subscribers: {},\n count: 0,\n };\n }\n return state;\n};\n\nconst storeState = (state: ModalCounterState): void => {\n storeValueInDom(STORAGE_NAME, state);\n};\n\nconst counterFactory = () => {\n return {\n updateVisiblility: (id: string, visible: boolean) => {\n // eslint-disable-next-line prefer-const\n const state = getState();\n const prevVisible = !!state.prevVisiblility[id];\n if (visible === prevVisible) {\n return;\n }\n state.prevVisiblility[id] = visible;\n if (visible) {\n state.count += 1;\n state.positions[id] = state.count;\n } else {\n state.count -= 1;\n const currentPosition = state.positions[id];\n state.positions[id] = 0;\n Object.entries(state.positions).forEach(([key, value]) => {\n state.positions[key] = value > currentPosition ? value - 1 : value;\n });\n }\n storeState(state);\n },\n subscribe: (id: string, callback: (position: NotifyCallbackArg) => void) => {\n const state = getState();\n state.subscribers[id] = callback;\n storeState(state);\n },\n unsubscribe: (id: string) => {\n const state = getState();\n delete state.subscribers[id];\n storeState(state);\n },\n notifyAll: () => {\n const { subscribers, count, positions } = getState();\n Object.entries(subscribers).forEach(([id, callback]) => callback({ position: positions[id], count }));\n },\n };\n};\n\nconst counter = counterFactory();\n\nexport const useModalOrder = (visible: boolean, modalRef: RefObject<HTMLDivElement>): [number, number] => {\n const [position, setPosition] = useState<{ position: number; count: number }>({ position: 0, count: 0 });\n const id = useDomStoredUniqueId();\n\n useLayoutEffect(() => {\n counter.updateVisiblility(id, visible);\n counter.notifyAll();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visible]);\n\n useEffect(() => {\n counter.subscribe(id, setPosition);\n counter.updateVisiblility(id, visible);\n return () => {\n counter.unsubscribe(id);\n counter.updateVisiblility(id, false);\n counter.notifyAll();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [id]);\n\n useLayoutEffect(() => {\n // Если это самый \"верхний\" модал передаем туда фокус\n if (position.position === position.count && position.count > 0) {\n modalRef.current?.focus();\n }\n }, [position, modalRef]);\n\n return [position.position, position.count];\n};\n"],"names":[],"mappings":"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"}
|