@alfalab/core-components-base-modal 5.9.0 → 6.0.0-snapshot-1393ffa

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.
Files changed (104) hide show
  1. package/Component.js +17 -18
  2. package/Component.js.map +1 -0
  3. package/cssm/Component.js +17 -16
  4. package/cssm/Component.js.map +1 -0
  5. package/cssm/helpers/lockScroll.js +1 -0
  6. package/cssm/helpers/lockScroll.js.map +1 -0
  7. package/cssm/index.js +6 -5
  8. package/cssm/index.js.map +1 -0
  9. package/cssm/index.module.css +3 -23
  10. package/cssm/matches-polyfill.js +1 -0
  11. package/cssm/matches-polyfill.js.map +1 -0
  12. package/{Component.d.ts → cssm/src/Component.d.ts} +8 -11
  13. package/cssm/src/helpers/lockScroll.d.ts +8 -0
  14. package/cssm/src/index.d.ts +3 -0
  15. package/cssm/src/utils.d.ts +5 -0
  16. package/cssm/utils.js +6 -5
  17. package/cssm/utils.js.map +1 -0
  18. package/esm/Component.js +3 -4
  19. package/esm/Component.js.map +1 -0
  20. package/esm/helpers/lockScroll.js +1 -0
  21. package/esm/helpers/lockScroll.js.map +1 -0
  22. package/esm/index.css +17 -38
  23. package/esm/index.js +1 -0
  24. package/esm/index.js.map +1 -0
  25. package/esm/index.module.css.js +6 -0
  26. package/esm/index.module.css.js.map +1 -0
  27. package/esm/matches-polyfill.js +1 -0
  28. package/esm/matches-polyfill.js.map +1 -0
  29. package/{cssm → esm/src}/Component.d.ts +8 -11
  30. package/esm/src/helpers/lockScroll.d.ts +8 -0
  31. package/esm/src/index.d.ts +3 -0
  32. package/esm/src/utils.d.ts +5 -0
  33. package/esm/utils.js +1 -0
  34. package/esm/utils.js.map +1 -0
  35. package/helpers/lockScroll.js +1 -0
  36. package/helpers/lockScroll.js.map +1 -0
  37. package/index.css +17 -38
  38. package/index.js +6 -5
  39. package/index.js.map +1 -0
  40. package/index.module.css.js +8 -0
  41. package/index.module.css.js.map +1 -0
  42. package/matches-polyfill.js +1 -0
  43. package/matches-polyfill.js.map +1 -0
  44. package/modern/Component.js +3 -4
  45. package/modern/Component.js.map +1 -0
  46. package/modern/helpers/lockScroll.js +1 -0
  47. package/modern/helpers/lockScroll.js.map +1 -0
  48. package/modern/index.css +17 -38
  49. package/modern/index.js +1 -0
  50. package/modern/index.js.map +1 -0
  51. package/modern/index.module.css.js +6 -0
  52. package/modern/index.module.css.js.map +1 -0
  53. package/modern/matches-polyfill.js +1 -0
  54. package/modern/matches-polyfill.js.map +1 -0
  55. package/{esm → modern/src}/Component.d.ts +8 -11
  56. package/modern/src/helpers/lockScroll.d.ts +8 -0
  57. package/modern/src/index.d.ts +3 -0
  58. package/modern/src/utils.d.ts +5 -0
  59. package/modern/utils.js +1 -0
  60. package/modern/utils.js.map +1 -0
  61. package/moderncssm/Component.js +2 -1
  62. package/moderncssm/Component.js.map +1 -0
  63. package/moderncssm/helpers/lockScroll.js +1 -0
  64. package/moderncssm/helpers/lockScroll.js.map +1 -0
  65. package/moderncssm/index.js +1 -0
  66. package/moderncssm/index.js.map +1 -0
  67. package/moderncssm/index.module.css +1 -3
  68. package/moderncssm/matches-polyfill.js +1 -0
  69. package/moderncssm/matches-polyfill.js.map +1 -0
  70. package/{modern → moderncssm/src}/Component.d.ts +8 -11
  71. package/moderncssm/src/helpers/lockScroll.d.ts +8 -0
  72. package/moderncssm/src/index.d.ts +3 -0
  73. package/moderncssm/src/utils.d.ts +5 -0
  74. package/moderncssm/utils.js +1 -0
  75. package/moderncssm/utils.js.map +1 -0
  76. package/package.json +10 -11
  77. package/src/Component.d.ts +164 -0
  78. package/src/Component.tsx +1 -1
  79. package/src/helpers/lockScroll.d.ts +8 -0
  80. package/src/index.d.ts +3 -0
  81. package/src/utils.d.ts +5 -0
  82. package/utils.js +1 -0
  83. package/utils.js.map +1 -0
  84. package/cssm/helpers/lockScroll.d.ts +0 -5
  85. package/cssm/index.d.ts +0 -3
  86. package/cssm/matches-polyfill.d.ts +0 -1
  87. package/cssm/utils.d.ts +0 -6
  88. package/esm/helpers/lockScroll.d.ts +0 -5
  89. package/esm/index.d.ts +0 -3
  90. package/esm/matches-polyfill.d.ts +0 -1
  91. package/esm/utils.d.ts +0 -6
  92. package/helpers/lockScroll.d.ts +0 -5
  93. package/index.d.ts +0 -3
  94. package/matches-polyfill.d.ts +0 -1
  95. package/modern/helpers/lockScroll.d.ts +0 -5
  96. package/modern/index.d.ts +0 -3
  97. package/modern/matches-polyfill.d.ts +0 -1
  98. package/modern/utils.d.ts +0 -6
  99. package/moderncssm/Component.d.ts +0 -167
  100. package/moderncssm/helpers/lockScroll.d.ts +0 -5
  101. package/moderncssm/index.d.ts +0 -3
  102. package/moderncssm/matches-polyfill.d.ts +0 -1
  103. package/moderncssm/utils.d.ts +0 -6
  104. package/utils.d.ts +0 -6
@@ -85,3 +85,4 @@ const handleContainer = (container, shouldIOSLock = false) => {
85
85
  };
86
86
 
87
87
  export { handleContainer, hasScrollbar, isScrolledToBottom, isScrolledToTop, restoreContainerStyles };
88
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import { getModalStore, SavedStyle } from '@alfalab/core-components-global-store';\nimport { browser } from '@alfalab/core-components-shared';\n\nexport function isScrolledToTop(target: HTMLElement) {\n return target.scrollTop <= 0;\n}\n\nexport function isScrolledToBottom(target: HTMLElement) {\n return target.scrollHeight - target.offsetHeight <= target.scrollTop;\n}\n\nexport function hasScrollbar(target: HTMLElement) {\n return target.scrollHeight > target.clientHeight;\n}\n\nconst isOverflowing = (container: Element) => {\n if (document.body === container) {\n return window.innerWidth > document.documentElement.clientWidth;\n }\n\n return container.scrollHeight > container.clientHeight;\n};\n\nconst getPaddingRight = (node: Element) =>\n parseInt(window.getComputedStyle(node).paddingRight, 10) || 0;\n\nexport const restoreContainerStyles = (container: HTMLElement) => {\n const modalRestoreStyles = getModalStore().getRestoreStyles();\n\n const index = modalRestoreStyles.findIndex((s) => s.container === container);\n const existingStyles = modalRestoreStyles[index];\n\n if (!existingStyles) return;\n\n existingStyles.modals -= 1;\n\n if (existingStyles.modals <= 0) {\n modalRestoreStyles.splice(index, 1);\n\n existingStyles.styles.forEach(({ value, el, key }) => {\n if (value) {\n el.style.setProperty(key, value);\n } else {\n el.style.removeProperty(key);\n }\n });\n }\n};\n\nexport const handleContainer = (container?: HTMLElement, shouldIOSLock = false) => {\n if (!container) return;\n\n const modalRestoreStyles = getModalStore().getRestoreStyles();\n\n const existingStyles = modalRestoreStyles.find((s) => s.container === container);\n\n if (existingStyles) {\n existingStyles.modals += 1;\n\n return;\n }\n\n const containerStyles: SavedStyle[] = [];\n\n if (isOverflowing(container)) {\n // Вычисляет размер до применения `overflow hidden` для избежания скачков\n const scrollbarSize = browser.getScrollbarSize();\n\n containerStyles.push({\n value: container.style.paddingRight,\n key: 'padding-right',\n el: container,\n });\n // Вычисляем стили, чтобы получить реальный `padding` c шириной сколлбара\n // eslint-disable-next-line no-param-reassign\n container.style.paddingRight = `${getPaddingRight(container) + scrollbarSize}px`;\n }\n\n const parent = container.parentElement;\n const scrollContainer =\n // TODO: заменить на optional chaining\n parent &&\n parent.nodeName === 'HTML' &&\n window.getComputedStyle(parent).overflowY === 'scroll'\n ? parent\n : container;\n\n // Блокируем скролл даже если отсутствует скроллбар\n if (scrollContainer.style.overflow !== 'hidden') {\n containerStyles.push({\n value: scrollContainer.style.overflow,\n key: 'overflow',\n el: scrollContainer,\n });\n }\n\n if (!shouldIOSLock) {\n scrollContainer.style.overflow = 'hidden';\n }\n\n modalRestoreStyles.push({\n container,\n modals: 1,\n styles: containerStyles,\n });\n};\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfalab/core-components-base-modal",
3
- "version": "5.9.0",
3
+ "version": "6.0.0-snapshot-1393ffa",
4
4
  "description": "BaseModal component",
5
5
  "keywords": [],
6
6
  "license": "MIT",
@@ -12,24 +12,23 @@
12
12
  },
13
13
  "sideEffects": false,
14
14
  "dependencies": {
15
- "@alfalab/core-components-backdrop": "^3.4.5",
16
- "@alfalab/core-components-global-store": "^2.1.0",
17
- "@alfalab/core-components-portal": "^3.3.7",
18
- "@alfalab/core-components-stack": "^5.0.1",
19
- "@alfalab/core-components-shared": "^0.16.0",
15
+ "@alfalab/core-components-backdrop": "3.4.6-snapshot-1393ffa",
16
+ "@alfalab/core-components-global-store": "2.1.1-snapshot-1393ffa",
17
+ "@alfalab/core-components-portal": "3.3.8-snapshot-1393ffa",
18
+ "@alfalab/core-components-stack": "6.0.0-snapshot-1393ffa",
19
+ "@alfalab/core-components-shared": "0.16.1-snapshot-1393ffa",
20
20
  "@juggle/resize-observer": "^3.3.1",
21
+ "@types/react-transition-group": "^4.4.5",
21
22
  "classnames": "^2.5.1",
22
23
  "react-focus-lock": "^2.12.1",
23
24
  "react-merge-refs": "^1.1.0",
24
25
  "react-transition-group": "^4.4.5",
25
26
  "tslib": "^2.4.0"
26
27
  },
27
- "devDependencies": {
28
- "@types/react-transition-group": "^4.4.5"
29
- },
30
28
  "peerDependencies": {
29
+ "@alfalab/core-components-stack-context": "1.0.0-snapshot-1393ffa",
31
30
  "react": "^16.9.0 || ^17.0.1 || ^18.0.0"
32
31
  },
33
- "themesVersion": "13.7.1",
34
- "varsVersion": "9.18.0"
32
+ "themesVersion": "14.0.0-snapshot-1393ffa",
33
+ "varsVersion": "9.20.1-snapshot-1393ffa"
35
34
  }
@@ -0,0 +1,164 @@
1
+ import React, { ComponentType, KeyboardEvent, MouseEvent, MutableRefObject, ReactNode, Ref, WheelEvent } from 'react';
2
+ import { TransitionProps } from 'react-transition-group/Transition';
3
+ import { BackdropProps } from '@alfalab/core-components-backdrop';
4
+ import { PortalProps } from '@alfalab/core-components-portal';
5
+ import './matches-polyfill';
6
+ export declare type BaseModalProps = {
7
+ /**
8
+ * Контент
9
+ */
10
+ children?: ReactNode;
11
+ /**
12
+ * Компонент бэкдропа
13
+ */
14
+ Backdrop?: ComponentType<BackdropProps>;
15
+ /**
16
+ * Свойства для Бэкдропа
17
+ */
18
+ backdropProps?: Partial<BackdropProps> & Record<string, unknown>;
19
+ /**
20
+ * Нода, компонент или функция возвращающая их
21
+ *
22
+ * Контейнер к которому будут добавляться порталы
23
+ */
24
+ container?: PortalProps['getPortalContainer'];
25
+ /**
26
+ * Отключает автоматический перевод фокуса на модалку при открытии
27
+ * @default false
28
+ */
29
+ disableAutoFocus?: boolean;
30
+ /**
31
+ * Отключает ловушку фокуса
32
+ * @default false
33
+ */
34
+ disableFocusLock?: boolean;
35
+ /**
36
+ * Отключает восстановление фокуса на предыдущем элементе после закрытия модалки
37
+ * @default false
38
+ */
39
+ disableRestoreFocus?: boolean;
40
+ /**
41
+ * Отключает вызов `callback` при нажатии Escape
42
+ * @default false
43
+ */
44
+ disableEscapeKeyDown?: boolean;
45
+ /**
46
+ * Отключает вызов `callback` при клике на бэкдроп
47
+ * @default false
48
+ */
49
+ disableBackdropClick?: boolean;
50
+ /**
51
+ * Отключает блокировку скролла при открытии модального окна
52
+ * @default false
53
+ */
54
+ disableBlockingScroll?: boolean;
55
+ /**
56
+ * Содержимое модалки всегда в DOM
57
+ * @default false
58
+ */
59
+ keepMounted?: boolean;
60
+ /**
61
+ * Управление видимостью модалки
62
+ */
63
+ open: boolean;
64
+ /**
65
+ * Дополнительный класс
66
+ */
67
+ className?: string;
68
+ /**
69
+ * Дополнительный класс
70
+ */
71
+ contentClassName?: string;
72
+ /**
73
+ * Дополнительные пропсы на dialog wrapper
74
+ */
75
+ wrapperProps?: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
76
+ /**
77
+ * Дополнительные пропсы на обертку контента
78
+ */
79
+ contentProps?: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
80
+ /**
81
+ * Дополнительные пропсы на компонентную обертку контента
82
+ */
83
+ componentDivProps?: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
84
+ /**
85
+ * Дополнительный класс для обертки (Modal)
86
+ */
87
+ wrapperClassName?: string;
88
+ /**
89
+ * Обработчик скролла контента
90
+ */
91
+ scrollHandler?: 'wrapper' | 'content' | MutableRefObject<HTMLDivElement | null>;
92
+ /**
93
+ * Пропсы для анимации (CSSTransition)
94
+ */
95
+ transitionProps?: Partial<TransitionProps>;
96
+ /**
97
+ * Рендерить ли в контейнер через портал.
98
+ * @default true
99
+ */
100
+ usePortal?: boolean;
101
+ /**
102
+ * Обработчик события нажатия на бэкдроп
103
+ */
104
+ onBackdropClick?: (event: MouseEvent) => void;
105
+ /**
106
+ * Обработчик события нажатия на Escape
107
+ *
108
+ * Если `disableEscapeKeyDown` - false и модальное окно в фокусе
109
+ */
110
+ onEscapeKeyDown?: (event: KeyboardEvent) => void;
111
+ /**
112
+ * Обработчик закрытия
113
+ */
114
+ onClose?: (event: MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement>, reason?: 'backdropClick' | 'escapeKeyDown' | 'closerClick') => void;
115
+ /**
116
+ * Обработчик события onEntered компонента Transition
117
+ */
118
+ onMount?: () => void;
119
+ /**
120
+ * Обработчик события onExited компонента Transition
121
+ */
122
+ onUnmount?: () => void;
123
+ /**
124
+ * Идентификатор для систем автоматизированного тестирования
125
+ */
126
+ dataTestId?: string;
127
+ /**
128
+ * z-index компонента
129
+ */
130
+ zIndex?: number;
131
+ /**
132
+ * Реф, который должен быть установлен компонентной области
133
+ */
134
+ componentRef?: MutableRefObject<HTMLDivElement | null>;
135
+ /**
136
+ * Реф контентной области
137
+ */
138
+ contentElementRef?: MutableRefObject<HTMLDivElement | null>;
139
+ /**
140
+ * Блокирует скролл когда модальное окно открыто. Работает только на iOS.
141
+ */
142
+ iOSLock?: boolean;
143
+ /**
144
+ * Хэндлер события прокрутки колесиком
145
+ */
146
+ onWheel?: (e: WheelEvent<HTMLElement>) => void;
147
+ };
148
+ export declare type BaseModalContext = {
149
+ parentRef: React.RefObject<HTMLDivElement>;
150
+ componentRef: React.RefObject<HTMLDivElement>;
151
+ hasFooter?: boolean;
152
+ hasHeader?: boolean;
153
+ hasScroll?: boolean;
154
+ headerHighlighted?: boolean;
155
+ footerHighlighted?: boolean;
156
+ headerOffset?: number;
157
+ setHeaderOffset: (offset: number) => void;
158
+ contentRef: Ref<HTMLElement>;
159
+ setHasHeader: (exists: boolean) => void;
160
+ setHasFooter: (exists: boolean) => void;
161
+ onClose: Required<BaseModalProps>['onClose'];
162
+ };
163
+ export declare const BaseModalContext: React.Context<BaseModalContext>;
164
+ export declare const BaseModal: React.ForwardRefExoticComponent<BaseModalProps & React.RefAttributes<HTMLDivElement>>;
package/src/Component.tsx CHANGED
@@ -25,7 +25,7 @@ import { Backdrop as DefaultBackdrop, BackdropProps } from '@alfalab/core-compon
25
25
  import { Portal, PortalProps } from '@alfalab/core-components-portal';
26
26
  import { browser, os } from '@alfalab/core-components-shared';
27
27
  import { Stack } from '@alfalab/core-components-stack';
28
- import { stackingOrder } from '@alfalab/stack-context';
28
+ import { stackingOrder } from '@alfalab/core-components-stack-context';
29
29
 
30
30
  import { lockScroll, syncHeight, unlockScroll } from './helpers/lockScroll';
31
31
  import {
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Хелпер для блокирования скроллинга в iOS
3
+ * В проекте используется overflow: hidden для блокировки, но в некоторых случаях этого недостаточно. Данный хелпер призван решать эту проблему
4
+ */
5
+ export declare const isScrollLocked: () => boolean;
6
+ export declare const lockScroll: () => void;
7
+ export declare const unlockScroll: () => void;
8
+ export declare const syncHeight: () => void;
package/src/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './Component';
2
+ export * from './utils';
3
+ export * from './helpers/lockScroll';
package/src/utils.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export declare function isScrolledToTop(target: HTMLElement): boolean;
2
+ export declare function isScrolledToBottom(target: HTMLElement): boolean;
3
+ export declare function hasScrollbar(target: HTMLElement): boolean;
4
+ export declare const restoreContainerStyles: (container: HTMLElement) => void;
5
+ export declare const handleContainer: (container?: HTMLElement, shouldIOSLock?: boolean) => void;
package/utils.js CHANGED
@@ -97,3 +97,4 @@ exports.hasScrollbar = hasScrollbar;
97
97
  exports.isScrolledToBottom = isScrolledToBottom;
98
98
  exports.isScrolledToTop = isScrolledToTop;
99
99
  exports.restoreContainerStyles = restoreContainerStyles;
100
+ //# sourceMappingURL=utils.js.map
package/utils.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../src/utils.ts"],"sourcesContent":["import { getModalStore, SavedStyle } from '@alfalab/core-components-global-store';\nimport { browser } from '@alfalab/core-components-shared';\n\nexport function isScrolledToTop(target: HTMLElement) {\n return target.scrollTop <= 0;\n}\n\nexport function isScrolledToBottom(target: HTMLElement) {\n return target.scrollHeight - target.offsetHeight <= target.scrollTop;\n}\n\nexport function hasScrollbar(target: HTMLElement) {\n return target.scrollHeight > target.clientHeight;\n}\n\nconst isOverflowing = (container: Element) => {\n if (document.body === container) {\n return window.innerWidth > document.documentElement.clientWidth;\n }\n\n return container.scrollHeight > container.clientHeight;\n};\n\nconst getPaddingRight = (node: Element) =>\n parseInt(window.getComputedStyle(node).paddingRight, 10) || 0;\n\nexport const restoreContainerStyles = (container: HTMLElement) => {\n const modalRestoreStyles = getModalStore().getRestoreStyles();\n\n const index = modalRestoreStyles.findIndex((s) => s.container === container);\n const existingStyles = modalRestoreStyles[index];\n\n if (!existingStyles) return;\n\n existingStyles.modals -= 1;\n\n if (existingStyles.modals <= 0) {\n modalRestoreStyles.splice(index, 1);\n\n existingStyles.styles.forEach(({ value, el, key }) => {\n if (value) {\n el.style.setProperty(key, value);\n } else {\n el.style.removeProperty(key);\n }\n });\n }\n};\n\nexport const handleContainer = (container?: HTMLElement, shouldIOSLock = false) => {\n if (!container) return;\n\n const modalRestoreStyles = getModalStore().getRestoreStyles();\n\n const existingStyles = modalRestoreStyles.find((s) => s.container === container);\n\n if (existingStyles) {\n existingStyles.modals += 1;\n\n return;\n }\n\n const containerStyles: SavedStyle[] = [];\n\n if (isOverflowing(container)) {\n // Вычисляет размер до применения `overflow hidden` для избежания скачков\n const scrollbarSize = browser.getScrollbarSize();\n\n containerStyles.push({\n value: container.style.paddingRight,\n key: 'padding-right',\n el: container,\n });\n // Вычисляем стили, чтобы получить реальный `padding` c шириной сколлбара\n // eslint-disable-next-line no-param-reassign\n container.style.paddingRight = `${getPaddingRight(container) + scrollbarSize}px`;\n }\n\n const parent = container.parentElement;\n const scrollContainer =\n // TODO: заменить на optional chaining\n parent &&\n parent.nodeName === 'HTML' &&\n window.getComputedStyle(parent).overflowY === 'scroll'\n ? parent\n : container;\n\n // Блокируем скролл даже если отсутствует скроллбар\n if (scrollContainer.style.overflow !== 'hidden') {\n containerStyles.push({\n value: scrollContainer.style.overflow,\n key: 'overflow',\n el: scrollContainer,\n });\n }\n\n if (!shouldIOSLock) {\n scrollContainer.style.overflow = 'hidden';\n }\n\n modalRestoreStyles.push({\n container,\n modals: 1,\n styles: containerStyles,\n });\n};\n"],"names":["getModalStore","browser"],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- declare const isScrollLocked: () => boolean;
2
- declare const lockScroll: () => void;
3
- declare const unlockScroll: () => void;
4
- declare const syncHeight: () => void;
5
- export { isScrollLocked, lockScroll, unlockScroll, syncHeight };
package/cssm/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from "./Component";
2
- export * from "./utils";
3
- export * from "./helpers/lockScroll";
@@ -1 +0,0 @@
1
- export {};
package/cssm/utils.d.ts DELETED
@@ -1,6 +0,0 @@
1
- declare function isScrolledToTop(target: HTMLElement): boolean;
2
- declare function isScrolledToBottom(target: HTMLElement): boolean;
3
- declare function hasScrollbar(target: HTMLElement): boolean;
4
- declare const restoreContainerStyles: (container: HTMLElement) => void;
5
- declare const handleContainer: (container?: HTMLElement, shouldIOSLock?: boolean) => void;
6
- export { isScrolledToTop, isScrolledToBottom, hasScrollbar, restoreContainerStyles, handleContainer };
@@ -1,5 +0,0 @@
1
- declare const isScrollLocked: () => boolean;
2
- declare const lockScroll: () => void;
3
- declare const unlockScroll: () => void;
4
- declare const syncHeight: () => void;
5
- export { isScrollLocked, lockScroll, unlockScroll, syncHeight };
package/esm/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from "./Component";
2
- export * from "./utils";
3
- export * from "./helpers/lockScroll";
@@ -1 +0,0 @@
1
- export {};
package/esm/utils.d.ts DELETED
@@ -1,6 +0,0 @@
1
- declare function isScrolledToTop(target: HTMLElement): boolean;
2
- declare function isScrolledToBottom(target: HTMLElement): boolean;
3
- declare function hasScrollbar(target: HTMLElement): boolean;
4
- declare const restoreContainerStyles: (container: HTMLElement) => void;
5
- declare const handleContainer: (container?: HTMLElement, shouldIOSLock?: boolean) => void;
6
- export { isScrolledToTop, isScrolledToBottom, hasScrollbar, restoreContainerStyles, handleContainer };
@@ -1,5 +0,0 @@
1
- declare const isScrollLocked: () => boolean;
2
- declare const lockScroll: () => void;
3
- declare const unlockScroll: () => void;
4
- declare const syncHeight: () => void;
5
- export { isScrollLocked, lockScroll, unlockScroll, syncHeight };
package/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from "./Component";
2
- export * from "./utils";
3
- export * from "./helpers/lockScroll";
@@ -1 +0,0 @@
1
- export {};
@@ -1,5 +0,0 @@
1
- declare const isScrollLocked: () => boolean;
2
- declare const lockScroll: () => void;
3
- declare const unlockScroll: () => void;
4
- declare const syncHeight: () => void;
5
- export { isScrollLocked, lockScroll, unlockScroll, syncHeight };
package/modern/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from "./Component";
2
- export * from "./utils";
3
- export * from "./helpers/lockScroll";
@@ -1 +0,0 @@
1
- export {};
package/modern/utils.d.ts DELETED
@@ -1,6 +0,0 @@
1
- declare function isScrolledToTop(target: HTMLElement): boolean;
2
- declare function isScrolledToBottom(target: HTMLElement): boolean;
3
- declare function hasScrollbar(target: HTMLElement): boolean;
4
- declare const restoreContainerStyles: (container: HTMLElement) => void;
5
- declare const handleContainer: (container?: HTMLElement, shouldIOSLock?: boolean) => void;
6
- export { isScrolledToTop, isScrolledToBottom, hasScrollbar, restoreContainerStyles, handleContainer };
@@ -1,167 +0,0 @@
1
- /// <reference types="react" />
2
- /// <reference types="react-transition-group" />
3
- import React from 'react';
4
- import { ComponentType, KeyboardEvent, MouseEvent, MutableRefObject, ReactNode, Ref, WheelEvent } from "react";
5
- import { TransitionProps } from 'react-transition-group/Transition';
6
- import { BackdropProps } from "@alfalab/core-components-backdrop";
7
- import { PortalProps } from "@alfalab/core-components-portal";
8
- type BaseModalProps = {
9
- /**
10
- * Контент
11
- */
12
- children?: ReactNode;
13
- /**
14
- * Компонент бэкдропа
15
- */
16
- Backdrop?: ComponentType<BackdropProps>;
17
- /**
18
- * Свойства для Бэкдропа
19
- */
20
- backdropProps?: Partial<BackdropProps> & Record<string, unknown>;
21
- /**
22
- * Нода, компонент или функция возвращающая их
23
- *
24
- * Контейнер к которому будут добавляться порталы
25
- */
26
- container?: PortalProps['getPortalContainer'];
27
- /**
28
- * Отключает автоматический перевод фокуса на модалку при открытии
29
- * @default false
30
- */
31
- disableAutoFocus?: boolean;
32
- /**
33
- * Отключает ловушку фокуса
34
- * @default false
35
- */
36
- disableFocusLock?: boolean;
37
- /**
38
- * Отключает восстановление фокуса на предыдущем элементе после закрытия модалки
39
- * @default false
40
- */
41
- disableRestoreFocus?: boolean;
42
- /**
43
- * Отключает вызов `callback` при нажатии Escape
44
- * @default false
45
- */
46
- disableEscapeKeyDown?: boolean;
47
- /**
48
- * Отключает вызов `callback` при клике на бэкдроп
49
- * @default false
50
- */
51
- disableBackdropClick?: boolean;
52
- /**
53
- * Отключает блокировку скролла при открытии модального окна
54
- * @default false
55
- */
56
- disableBlockingScroll?: boolean;
57
- /**
58
- * Содержимое модалки всегда в DOM
59
- * @default false
60
- */
61
- keepMounted?: boolean;
62
- /**
63
- * Управление видимостью модалки
64
- */
65
- open: boolean;
66
- /**
67
- * Дополнительный класс
68
- */
69
- className?: string;
70
- /**
71
- * Дополнительный класс
72
- */
73
- contentClassName?: string;
74
- /**
75
- * Дополнительные пропсы на dialog wrapper
76
- */
77
- wrapperProps?: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
78
- /**
79
- * Дополнительные пропсы на обертку контента
80
- */
81
- contentProps?: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
82
- /**
83
- * Дополнительные пропсы на компонентную обертку контента
84
- */
85
- componentDivProps?: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
86
- /**
87
- * Дополнительный класс для обертки (Modal)
88
- */
89
- wrapperClassName?: string;
90
- /**
91
- * Обработчик скролла контента
92
- */
93
- scrollHandler?: 'wrapper' | 'content' | MutableRefObject<HTMLDivElement | null>;
94
- /**
95
- * Пропсы для анимации (CSSTransition)
96
- */
97
- transitionProps?: Partial<TransitionProps>;
98
- /**
99
- * Рендерить ли в контейнер через портал.
100
- * @default true
101
- */
102
- usePortal?: boolean;
103
- /**
104
- * Обработчик события нажатия на бэкдроп
105
- */
106
- onBackdropClick?: (event: MouseEvent) => void;
107
- /**
108
- * Обработчик события нажатия на Escape
109
- *
110
- * Если `disableEscapeKeyDown` - false и модальное окно в фокусе
111
- */
112
- onEscapeKeyDown?: (event: KeyboardEvent) => void;
113
- /**
114
- * Обработчик закрытия
115
- */
116
- onClose?: (event: MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement>, reason?: 'backdropClick' | 'escapeKeyDown' | 'closerClick') => void;
117
- /**
118
- * Обработчик события onEntered компонента Transition
119
- */
120
- onMount?: () => void;
121
- /**
122
- * Обработчик события onExited компонента Transition
123
- */
124
- onUnmount?: () => void;
125
- /**
126
- * Идентификатор для систем автоматизированного тестирования
127
- */
128
- dataTestId?: string;
129
- /**
130
- * z-index компонента
131
- */
132
- zIndex?: number;
133
- /**
134
- * Реф, который должен быть установлен компонентной области
135
- */
136
- componentRef?: MutableRefObject<HTMLDivElement | null>;
137
- /**
138
- * Реф контентной области
139
- */
140
- contentElementRef?: MutableRefObject<HTMLDivElement | null>;
141
- /**
142
- * Блокирует скролл когда модальное окно открыто. Работает только на iOS.
143
- */
144
- iOSLock?: boolean;
145
- /**
146
- * Хэндлер события прокрутки колесиком
147
- */
148
- onWheel?: (e: WheelEvent<HTMLElement>) => void;
149
- };
150
- type BaseModalContext = {
151
- parentRef: React.RefObject<HTMLDivElement>;
152
- componentRef: React.RefObject<HTMLDivElement>;
153
- hasFooter?: boolean;
154
- hasHeader?: boolean;
155
- hasScroll?: boolean;
156
- headerHighlighted?: boolean;
157
- footerHighlighted?: boolean;
158
- headerOffset?: number;
159
- setHeaderOffset: (offset: number) => void;
160
- contentRef: Ref<HTMLElement>;
161
- setHasHeader: (exists: boolean) => void;
162
- setHasFooter: (exists: boolean) => void;
163
- onClose: Required<BaseModalProps>['onClose'];
164
- };
165
- declare const BaseModalContext: React.Context<BaseModalContext>;
166
- declare const BaseModal: React.ForwardRefExoticComponent<BaseModalProps & React.RefAttributes<HTMLDivElement>>;
167
- export { BaseModalProps, BaseModalContext, BaseModal };
@@ -1,5 +0,0 @@
1
- declare const isScrollLocked: () => boolean;
2
- declare const lockScroll: () => void;
3
- declare const unlockScroll: () => void;
4
- declare const syncHeight: () => void;
5
- export { isScrollLocked, lockScroll, unlockScroll, syncHeight };
@@ -1,3 +0,0 @@
1
- export * from "./Component";
2
- export * from "./utils";
3
- export * from "./helpers/lockScroll";
@@ -1 +0,0 @@
1
- export {};
@@ -1,6 +0,0 @@
1
- declare function isScrolledToTop(target: HTMLElement): boolean;
2
- declare function isScrolledToBottom(target: HTMLElement): boolean;
3
- declare function hasScrollbar(target: HTMLElement): boolean;
4
- declare const restoreContainerStyles: (container: HTMLElement) => void;
5
- declare const handleContainer: (container?: HTMLElement, shouldIOSLock?: boolean) => void;
6
- export { isScrolledToTop, isScrolledToBottom, hasScrollbar, restoreContainerStyles, handleContainer };
package/utils.d.ts DELETED
@@ -1,6 +0,0 @@
1
- declare function isScrolledToTop(target: HTMLElement): boolean;
2
- declare function isScrolledToBottom(target: HTMLElement): boolean;
3
- declare function hasScrollbar(target: HTMLElement): boolean;
4
- declare const restoreContainerStyles: (container: HTMLElement) => void;
5
- declare const handleContainer: (container?: HTMLElement, shouldIOSLock?: boolean) => void;
6
- export { isScrolledToTop, isScrolledToBottom, hasScrollbar, restoreContainerStyles, handleContainer };