@kne/react-modal 0.1.9 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
- import { useRef, useEffect, useState, useCallback, memo, forwardRef, useImperativeHandle, createRef, Children } from 'react';
1
+ import { useEffect, useRef, useState, useCallback, memo, forwardRef, useImperativeHandle, createRef, Children } from 'react';
2
2
  import { Modal as Modal$1, App, Button, Drawer as Drawer$1, Tabs } from 'antd';
3
3
  import { CloseOutlined, InfoCircleFilled, ExclamationCircleFilled, CloseCircleFilled, CheckCircleFilled } from '@ant-design/icons';
4
4
  import classnames from 'classnames';
5
- import { useMobilePopupMount, useScrollElement } from '@kne/responsive-utils';
5
+ import { usePopupMount, useScrollElement, hoistOutOfModalRoot } from '@kne/responsive-utils';
6
6
  import { createWithIntlProvider, useIntl } from '@kne/react-intl';
7
7
  import ButtonGroup from '@kne/button-group';
8
8
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -125,6 +125,54 @@ const Footer = ({
125
125
  });
126
126
  };
127
127
 
128
+ let parentScrollLockCount = 0;
129
+ let parentScrollLocked = [];
130
+
131
+ /** Modal / Drawer 共用:锁 body + layout scroll,避免背后页面滚动 */
132
+ const lockParentScroll = getScrollElement => {
133
+ parentScrollLockCount += 1;
134
+ if (parentScrollLockCount === 1) {
135
+ const targets = [document.body];
136
+ const scrollEl = typeof getScrollElement === 'function' ? getScrollElement() : null;
137
+ if (scrollEl && scrollEl !== document.body && !targets.includes(scrollEl)) {
138
+ targets.push(scrollEl);
139
+ }
140
+ parentScrollLocked = targets.map(el => {
141
+ const prev = {
142
+ overflow: el.style.overflow,
143
+ overscrollBehavior: el.style.overscrollBehavior
144
+ };
145
+ el.style.overflow = 'hidden';
146
+ el.style.overscrollBehavior = 'none';
147
+ return {
148
+ el,
149
+ prev
150
+ };
151
+ });
152
+ }
153
+ return () => {
154
+ parentScrollLockCount = Math.max(0, parentScrollLockCount - 1);
155
+ if (parentScrollLockCount === 0) {
156
+ parentScrollLocked.forEach(({
157
+ el,
158
+ prev
159
+ }) => {
160
+ el.style.overflow = prev.overflow;
161
+ el.style.overscrollBehavior = prev.overscrollBehavior;
162
+ });
163
+ parentScrollLocked = [];
164
+ }
165
+ };
166
+ };
167
+ const useLockParentScroll = (enabled, getScrollElement) => {
168
+ useEffect(() => {
169
+ if (!enabled) {
170
+ return undefined;
171
+ }
172
+ return lockParentScroll(getScrollElement);
173
+ }, [enabled, getScrollElement]);
174
+ };
175
+
128
176
  const _excluded$6 = ["children", "footer", "footerButtons", "className", "size", "title", "onClose", "onConfirm", "confirmText", "onCancel", "cancelText", "closable", "noPadding", "bodyScroll", "isMobile", "mobileFullscreen", "fixedModeClass", "wrapClassName", "classNames", "styles", "style", "modalRender"],
129
177
  _excluded2$3 = ["width"],
130
178
  _excluded3$1 = ["size", "getContainer", "open", "mobileFullscreen", "bodyScroll"],
@@ -149,20 +197,10 @@ const wrapCustomGetContainer$2 = customGetContainer => {
149
197
  return () => customGetContainer;
150
198
  };
151
199
  const VIEWPORT_EXAMPLE_SELECTORS$3 = ['.example-driver-device-scroll'];
152
- const viewportPopupMountOptions$1 = {
200
+ const viewportPopupMountOptions$3 = {
153
201
  cover: 'viewport',
154
202
  exampleSelectors: VIEWPORT_EXAMPLE_SELECTORS$3
155
203
  };
156
- const findParentModalMountHost = node => {
157
- if (!node || typeof node.closest !== 'function') {
158
- return null;
159
- }
160
- const parentRoot = node.closest('.ant-modal-root');
161
- if (!parentRoot) {
162
- return null;
163
- }
164
- return parentRoot.parentElement || (typeof document !== 'undefined' ? document.body : null);
165
- };
166
204
  const resolveModalGetContainer = ({
167
205
  customGetContainer,
168
206
  getPopupContainer,
@@ -177,58 +215,13 @@ const resolveModalGetContainer = ({
177
215
  }
178
216
  }
179
217
  const from = triggerNode || (typeof getHostNode === 'function' ? getHostNode() : null);
180
- const nestedHost = findParentModalMountHost(from);
218
+ const nestedHost = hoistOutOfModalRoot(from);
181
219
  if (nestedHost) {
182
220
  return nestedHost;
183
221
  }
184
222
  return getPopupContainer(triggerNode);
185
223
  };
186
224
  };
187
- let parentScrollLockCount$1 = 0;
188
- let parentScrollLocked$1 = [];
189
- const lockParentScroll$1 = getScrollElement => {
190
- parentScrollLockCount$1 += 1;
191
- if (parentScrollLockCount$1 === 1) {
192
- const targets = [document.body];
193
- const scrollEl = typeof getScrollElement === 'function' ? getScrollElement() : null;
194
- if (scrollEl && scrollEl !== document.body && !targets.includes(scrollEl)) {
195
- targets.push(scrollEl);
196
- }
197
- parentScrollLocked$1 = targets.map(el => {
198
- const prev = {
199
- overflow: el.style.overflow,
200
- overscrollBehavior: el.style.overscrollBehavior
201
- };
202
- el.style.overflow = 'hidden';
203
- el.style.overscrollBehavior = 'none';
204
- return {
205
- el,
206
- prev
207
- };
208
- });
209
- }
210
- return () => {
211
- parentScrollLockCount$1 = Math.max(0, parentScrollLockCount$1 - 1);
212
- if (parentScrollLockCount$1 === 0) {
213
- parentScrollLocked$1.forEach(({
214
- el,
215
- prev
216
- }) => {
217
- el.style.overflow = prev.overflow;
218
- el.style.overscrollBehavior = prev.overscrollBehavior;
219
- });
220
- parentScrollLocked$1 = [];
221
- }
222
- };
223
- };
224
- const useLockParentScroll$1 = (enabled, getScrollElement) => {
225
- useEffect(() => {
226
- if (!enabled) {
227
- return undefined;
228
- }
229
- return lockParentScroll$1(getScrollElement);
230
- }, [enabled, getScrollElement]);
231
- };
232
225
  const sizeStyleVars$1 = (size, hasFooter) => {
233
226
  const minBase = size === 'small' ? 300 : 500;
234
227
  const chrome = 48 + (hasFooter ? 58 : 0);
@@ -274,6 +267,15 @@ const ModalOuter = ({
274
267
  children: children
275
268
  });
276
269
  const bodyClassName = classnames(modalStyle['modal-body'], 'modal-body');
270
+ // 移动端全屏:body 用 flex 吃满 title/footer 之间剩余高度,footer 才能贴底;
271
+ // 勿写死 --kne-modal-body-height(高度受限类会把该值压矮,footer 悬在中间)
272
+ const bodyStyle = isMobile ? {
273
+ flex: '1 1 auto',
274
+ minHeight: 0,
275
+ height: 'auto'
276
+ } : {
277
+ height: 'var(--kne-modal-body-height)'
278
+ };
277
279
  return /*#__PURE__*/jsxs("div", {
278
280
  className: classnames(modalStyle['modal-outer'], 'modal-container', {
279
281
  [modalStyle['is-mobile']]: isMobile,
@@ -296,12 +298,14 @@ const ModalOuter = ({
296
298
  children: title
297
299
  }) : null, bodyScroll !== false ? /*#__PURE__*/jsx(SimpleBar, {
298
300
  className: bodyClassName,
299
- style: {
300
- height: 'var(--kne-modal-body-height)'
301
- },
301
+ style: bodyStyle,
302
302
  children: bodyInner
303
303
  }) : /*#__PURE__*/jsx("div", {
304
304
  className: classnames(bodyClassName, modalStyle['body-scroll-off']),
305
+ style: isMobile ? {
306
+ flex: '1 1 auto',
307
+ minHeight: 0
308
+ } : undefined,
305
309
  children: bodyInner
306
310
  }), footer === null && footerButtons === undefined ? null : /*#__PURE__*/jsx(Footer, {
307
311
  footer: footer,
@@ -444,11 +448,11 @@ const Modal = withLocale(_ref2 => {
444
448
  fixedModeClass,
445
449
  getPopupContainer,
446
450
  anchorRef
447
- } = useMobilePopupMount(_extends({}, viewportPopupMountOptions$1, {
451
+ } = usePopupMount(_extends({}, viewportPopupMountOptions$3, {
448
452
  getPopupContainer: wrapCustomGetContainer$2(getContainer)
449
453
  }));
450
454
  const getScrollElement = useScrollElement();
451
- useLockParentScroll$1(!!open, getScrollElement);
455
+ useLockParentScroll(!!open, getScrollElement);
452
456
  const setAnchorRef = node => {
453
457
  hostRef.current = node;
454
458
  anchorRef(node);
@@ -483,7 +487,7 @@ const useModal = () => {
483
487
  const {
484
488
  resolveMount,
485
489
  getPopupContainer
486
- } = useMobilePopupMount(viewportPopupMountOptions$1);
490
+ } = usePopupMount(viewportPopupMountOptions$3);
487
491
  const getScrollElement = useScrollElement();
488
492
  return props => {
489
493
  const anchor = typeof document !== 'undefined' ? document.activeElement : null;
@@ -491,7 +495,7 @@ const useModal = () => {
491
495
  isMobile,
492
496
  fixedModeClass
493
497
  } = resolveMount(anchor);
494
- const unlock = lockParentScroll$1(getScrollElement);
498
+ const unlock = lockParentScroll(getScrollElement);
495
499
  const api = {};
496
500
  const {
497
501
  afterClose: userAfterClose,
@@ -558,8 +562,10 @@ const DrawerLocaleRoot = withLocale(({
558
562
  children
559
563
  }) => children);
560
564
  const VIEWPORT_EXAMPLE_SELECTORS$2 = ['.example-driver-device-scroll'];
561
- const boundaryPopupMountOptions$1 = {
562
- cover: 'boundary',
565
+
566
+ // 与 Modal 一致:真机挂 body+fixed;示例框 / container 模式仍走 boundary(usePopupMount 内判定)
567
+ const viewportPopupMountOptions$2 = {
568
+ cover: 'viewport',
563
569
  exampleSelectors: VIEWPORT_EXAMPLE_SELECTORS$2
564
570
  };
565
571
  const renderWithOptions = (value, options) => {
@@ -609,51 +615,6 @@ const resolveDrawerGetContainer = ({
609
615
  return getPopupContainer(triggerNode);
610
616
  };
611
617
  };
612
- let parentScrollLockCount = 0;
613
- let parentScrollLocked = [];
614
- const lockParentScroll = getScrollElement => {
615
- parentScrollLockCount += 1;
616
- if (parentScrollLockCount === 1) {
617
- const targets = [document.body];
618
- const scrollEl = typeof getScrollElement === 'function' ? getScrollElement() : null;
619
- if (scrollEl && scrollEl !== document.body && !targets.includes(scrollEl)) {
620
- targets.push(scrollEl);
621
- }
622
- parentScrollLocked = targets.map(el => {
623
- const prev = {
624
- overflow: el.style.overflow,
625
- overscrollBehavior: el.style.overscrollBehavior
626
- };
627
- el.style.overflow = 'hidden';
628
- el.style.overscrollBehavior = 'none';
629
- return {
630
- el,
631
- prev
632
- };
633
- });
634
- }
635
- return () => {
636
- parentScrollLockCount = Math.max(0, parentScrollLockCount - 1);
637
- if (parentScrollLockCount === 0) {
638
- parentScrollLocked.forEach(({
639
- el,
640
- prev
641
- }) => {
642
- el.style.overflow = prev.overflow;
643
- el.style.overscrollBehavior = prev.overscrollBehavior;
644
- });
645
- parentScrollLocked = [];
646
- }
647
- };
648
- };
649
- const useLockParentScroll = (enabled, getScrollElement) => {
650
- useEffect(() => {
651
- if (!enabled) {
652
- return undefined;
653
- }
654
- return lockParentScroll(getScrollElement);
655
- }, [enabled, getScrollElement]);
656
- };
657
618
  const sizeStyleVars = (size, hasFooter) => {
658
619
  const minBase = size === 'small' ? 300 : 500;
659
620
  const chrome = 48 + (hasFooter ? 69 : 0);
@@ -890,7 +851,7 @@ const Drawer = withLocale(_ref2 => {
890
851
  fixedModeClass,
891
852
  getPopupContainer,
892
853
  anchorRef
893
- } = useMobilePopupMount(_extends({}, boundaryPopupMountOptions$1, {
854
+ } = usePopupMount(_extends({}, viewportPopupMountOptions$2, {
894
855
  getPopupContainer: wrapCustomGetContainer$1(getContainer)
895
856
  }));
896
857
  const getScrollElement = useScrollElement();
@@ -937,8 +898,10 @@ const usePatchElement = () => {
937
898
  const _excluded$4 = ["getContainer", "afterClose"],
938
899
  _excluded2$1 = ["afterClose", "getContainer"];
939
900
  const VIEWPORT_EXAMPLE_SELECTORS$1 = ['.example-driver-device-scroll'];
940
- const boundaryPopupMountOptions = {
941
- cover: 'boundary',
901
+
902
+ // 与 Modal / Drawer 一致:真机 viewport;示例框 / container 仍 boundary
903
+ const viewportPopupMountOptions$1 = {
904
+ cover: 'viewport',
942
905
  exampleSelectors: VIEWPORT_EXAMPLE_SELECTORS$1
943
906
  };
944
907
  const wrapCustomGetContainer = customGetContainer => {
@@ -964,7 +927,7 @@ const HookDrawer = /*#__PURE__*/forwardRef(({
964
927
  const {
965
928
  getPopupContainer,
966
929
  anchorRef
967
- } = useMobilePopupMount(_extends({}, boundaryPopupMountOptions, {
930
+ } = usePopupMount(_extends({}, viewportPopupMountOptions$1, {
968
931
  getPopupContainer: wrapCustomGetContainer(innerConfig.getContainer)
969
932
  }));
970
933
  const close = () => {
@@ -1028,7 +991,7 @@ const useDrawerHolder = () => {
1028
991
  const {
1029
992
  resolveMount,
1030
993
  getPopupContainer
1031
- } = useMobilePopupMount(boundaryPopupMountOptions);
994
+ } = usePopupMount(viewportPopupMountOptions$1);
1032
995
  const getScrollElement = useScrollElement();
1033
996
  useEffect(() => {
1034
997
  if (actionQueue.length) {
@@ -1293,7 +1256,7 @@ const useConfirmModal = () => {
1293
1256
  const {
1294
1257
  resolveMount,
1295
1258
  getPopupContainer
1296
- } = useMobilePopupMount(viewportPopupMountOptions);
1259
+ } = usePopupMount(viewportPopupMountOptions);
1297
1260
  const getScrollElement = useScrollElement();
1298
1261
  return props => {
1299
1262
  const anchor = typeof document !== 'undefined' ? document.activeElement : null;
@@ -1301,7 +1264,7 @@ const useConfirmModal = () => {
1301
1264
  isMobile,
1302
1265
  fixedModeClass
1303
1266
  } = resolveMount(anchor);
1304
- const unlock = lockParentScroll$1(getScrollElement);
1267
+ const unlock = lockParentScroll(getScrollElement);
1305
1268
  const api = {};
1306
1269
  const {
1307
1270
  afterClose: userAfterClose