@nocobase/flow-engine 2.1.25 → 2.1.27

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.
@@ -47,25 +47,36 @@ var import_react_i18next = require("react-i18next");
47
47
  var import_lazy_helper = require("../lazy-helper");
48
48
  const { Popup } = (0, import_lazy_helper.lazy)(() => import("antd-mobile"), "Popup");
49
49
  const { CloseOutline } = (0, import_lazy_helper.lazy)(() => import("antd-mobile-icons"), "CloseOutline");
50
+ const getMobilePopupMaxHeight = /* @__PURE__ */ __name(() => {
51
+ var _a;
52
+ if (typeof CSS !== "undefined" && ((_a = CSS.supports) == null ? void 0 : _a.call(CSS, "height", "100dvh"))) {
53
+ return "calc(100dvh - var(--nb-mobile-page-header-height, 46px))";
54
+ }
55
+ return "calc(100vh - var(--nb-mobile-page-header-height, 46px))";
56
+ }, "getMobilePopupMaxHeight");
50
57
  const MobilePopup = /* @__PURE__ */ __name((props) => {
51
58
  var _a;
52
59
  const { title, visible, onClose: closePopup, children, minHeight, className, footer } = props;
53
60
  const { t } = (0, import_react_i18next.useTranslation)();
54
61
  const { componentCls, hashId } = (0, import_MobilePopup.useMobileActionDrawerStyle)();
55
62
  const bodyStyles = (_a = props.styles) == null ? void 0 : _a.body;
63
+ const defaultMaxHeight = getMobilePopupMaxHeight();
56
64
  const popupStyle = (0, import_react.useMemo)(() => {
57
65
  return {
58
66
  minHeight: (bodyStyles == null ? void 0 : bodyStyles.minHeight) ?? minHeight,
59
67
  height: bodyStyles == null ? void 0 : bodyStyles.height,
60
- maxHeight: bodyStyles == null ? void 0 : bodyStyles.maxHeight
68
+ maxHeight: (bodyStyles == null ? void 0 : bodyStyles.maxHeight) ?? defaultMaxHeight
61
69
  };
62
- }, [bodyStyles == null ? void 0 : bodyStyles.height, bodyStyles == null ? void 0 : bodyStyles.maxHeight, bodyStyles == null ? void 0 : bodyStyles.minHeight, minHeight]);
70
+ }, [bodyStyles == null ? void 0 : bodyStyles.height, bodyStyles == null ? void 0 : bodyStyles.maxHeight, bodyStyles == null ? void 0 : bodyStyles.minHeight, defaultMaxHeight, minHeight]);
63
71
  const bodyStyle = (0, import_react.useMemo)(() => {
64
72
  return {
65
73
  padding: 0,
74
+ maxHeight: defaultMaxHeight,
75
+ overflowY: "auto",
76
+ overflowX: "hidden",
66
77
  ...bodyStyles
67
78
  };
68
- }, [bodyStyles]);
79
+ }, [bodyStyles, defaultMaxHeight]);
69
80
  const handleCloseKeyDown = (0, import_react.useCallback)(
70
81
  (event) => {
71
82
  if (event.key !== "Enter" && event.key !== " ") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/flow-engine",
3
- "version": "2.1.25",
3
+ "version": "2.1.27",
4
4
  "private": false,
5
5
  "description": "A standalone flow engine for NocoBase, managing workflows, models, and actions.",
6
6
  "main": "lib/index.js",
@@ -8,8 +8,8 @@
8
8
  "dependencies": {
9
9
  "@formily/antd-v5": "1.x",
10
10
  "@formily/reactive": "2.x",
11
- "@nocobase/sdk": "2.1.25",
12
- "@nocobase/shared": "2.1.25",
11
+ "@nocobase/sdk": "2.1.27",
12
+ "@nocobase/shared": "2.1.27",
13
13
  "ahooks": "^3.7.2",
14
14
  "axios": "^1.7.0",
15
15
  "dayjs": "^1.11.9",
@@ -37,5 +37,5 @@
37
37
  ],
38
38
  "author": "NocoBase Team",
39
39
  "license": "Apache-2.0",
40
- "gitHead": "f3326a2681004deee97b563fb6ab04744e26ac71"
40
+ "gitHead": "c1311c48cf65f8eeac17411d3380ebdd0918f1e2"
41
41
  }
@@ -26,26 +26,38 @@ interface MobilePopupProps {
26
26
  footer?: ReactNode;
27
27
  }
28
28
 
29
+ const getMobilePopupMaxHeight = () => {
30
+ if (typeof CSS !== 'undefined' && CSS.supports?.('height', '100dvh')) {
31
+ return 'calc(100dvh - var(--nb-mobile-page-header-height, 46px))';
32
+ }
33
+
34
+ return 'calc(100vh - var(--nb-mobile-page-header-height, 46px))';
35
+ };
36
+
29
37
  export const MobilePopup: FC<MobilePopupProps> = (props) => {
30
38
  const { title, visible, onClose: closePopup, children, minHeight, className, footer } = props;
31
39
  const { t } = useTranslation();
32
40
  const { componentCls, hashId } = useMobileActionDrawerStyle();
33
41
 
34
42
  const bodyStyles = (props as MobilePopupProps & { styles?: { body?: React.CSSProperties } }).styles?.body;
43
+ const defaultMaxHeight = getMobilePopupMaxHeight();
35
44
  const popupStyle = useMemo(() => {
36
45
  return {
37
46
  minHeight: bodyStyles?.minHeight ?? minHeight,
38
47
  height: bodyStyles?.height,
39
- maxHeight: bodyStyles?.maxHeight,
48
+ maxHeight: bodyStyles?.maxHeight ?? defaultMaxHeight,
40
49
  };
41
- }, [bodyStyles?.height, bodyStyles?.maxHeight, bodyStyles?.minHeight, minHeight]);
50
+ }, [bodyStyles?.height, bodyStyles?.maxHeight, bodyStyles?.minHeight, defaultMaxHeight, minHeight]);
42
51
 
43
- const bodyStyle = useMemo(() => {
52
+ const bodyStyle = useMemo<React.CSSProperties>(() => {
44
53
  return {
45
54
  padding: 0,
55
+ maxHeight: defaultMaxHeight,
56
+ overflowY: 'auto',
57
+ overflowX: 'hidden',
46
58
  ...bodyStyles,
47
59
  };
48
- }, [bodyStyles]);
60
+ }, [bodyStyles, defaultMaxHeight]);
49
61
 
50
62
  const handleCloseKeyDown = useCallback(
51
63
  (event: React.KeyboardEvent<HTMLSpanElement>) => {
@@ -9,7 +9,7 @@
9
9
 
10
10
  import React from 'react';
11
11
  import { fireEvent, render, screen } from '@testing-library/react';
12
- import { describe, expect, it, vi } from 'vitest';
12
+ import { afterEach, describe, expect, it, vi } from 'vitest';
13
13
  import { MobilePopup } from '../MobilePopup';
14
14
 
15
15
  vi.mock('react-i18next', () => ({
@@ -61,6 +61,47 @@ describe('MobilePopup', () => {
61
61
  React.ComponentProps<typeof MobilePopup> & { styles?: { body?: React.CSSProperties } }
62
62
  >;
63
63
 
64
+ afterEach(() => {
65
+ vi.unstubAllGlobals();
66
+ });
67
+
68
+ it('constrains the default popup to the dynamic viewport and keeps the body scrollable', () => {
69
+ vi.stubGlobal('CSS', {
70
+ supports: vi.fn((property: string, value: string) => property === 'height' && value === '100dvh'),
71
+ });
72
+
73
+ render(
74
+ <MobilePopup visible title="Title" onClose={vi.fn()}>
75
+ body
76
+ </MobilePopup>,
77
+ );
78
+
79
+ const maxHeight = 'calc(100dvh - var(--nb-mobile-page-header-height, 46px))';
80
+
81
+ expect(screen.getByTestId('mobile-popup')).toHaveStyle({ maxHeight });
82
+ expect(screen.getByTestId('mobile-popup-body')).toHaveStyle({
83
+ maxHeight,
84
+ overflowY: 'auto',
85
+ overflowX: 'hidden',
86
+ });
87
+ });
88
+
89
+ it('falls back to the layout viewport when dynamic viewport units are unavailable', () => {
90
+ vi.stubGlobal('CSS', {
91
+ supports: vi.fn(() => false),
92
+ });
93
+
94
+ render(
95
+ <MobilePopup visible title="Title" onClose={vi.fn()}>
96
+ body
97
+ </MobilePopup>,
98
+ );
99
+
100
+ expect(screen.getByTestId('mobile-popup-body')).toHaveStyle({
101
+ maxHeight: 'calc(100vh - var(--nb-mobile-page-header-height, 46px))',
102
+ });
103
+ });
104
+
64
105
  it('applies drawer body styles as max bounds without forcing fixed half-window height', () => {
65
106
  render(
66
107
  <MobilePopupWithDrawerStyles visible title="Title" styles={{ body: { maxHeight: '50vh' } }} onClose={vi.fn()}>