@nocobase/flow-engine 2.1.0-alpha.3 → 2.1.0-alpha.30

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 (160) hide show
  1. package/LICENSE +201 -661
  2. package/README.md +79 -10
  3. package/lib/JSRunner.d.ts +10 -1
  4. package/lib/JSRunner.js +50 -5
  5. package/lib/ViewScopedFlowEngine.js +5 -1
  6. package/lib/components/FieldModelRenderer.js +2 -2
  7. package/lib/components/FlowModelRenderer.d.ts +3 -1
  8. package/lib/components/FlowModelRenderer.js +12 -6
  9. package/lib/components/MobilePopup.js +6 -5
  10. package/lib/components/dnd/gridDragPlanner.d.ts +59 -2
  11. package/lib/components/dnd/gridDragPlanner.js +601 -21
  12. package/lib/components/dnd/index.d.ts +19 -1
  13. package/lib/components/dnd/index.js +243 -23
  14. package/lib/components/settings/wrappers/component/SelectWithTitle.d.ts +2 -1
  15. package/lib/components/settings/wrappers/component/SelectWithTitle.js +14 -12
  16. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +3 -0
  17. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +68 -10
  18. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +23 -43
  19. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +352 -295
  20. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +16 -2
  21. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.d.ts +36 -0
  22. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.js +274 -0
  23. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.d.ts +30 -0
  24. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.js +315 -0
  25. package/lib/components/subModel/AddSubModelButton.js +27 -1
  26. package/lib/components/subModel/index.d.ts +1 -0
  27. package/lib/components/subModel/index.js +19 -0
  28. package/lib/components/subModel/utils.d.ts +1 -1
  29. package/lib/components/subModel/utils.js +2 -2
  30. package/lib/data-source/index.d.ts +73 -0
  31. package/lib/data-source/index.js +211 -1
  32. package/lib/executor/FlowExecutor.js +31 -8
  33. package/lib/flowContext.d.ts +2 -0
  34. package/lib/flowContext.js +31 -1
  35. package/lib/flowEngine.d.ts +151 -1
  36. package/lib/flowEngine.js +389 -15
  37. package/lib/flowI18n.js +2 -1
  38. package/lib/flowSettings.d.ts +14 -6
  39. package/lib/flowSettings.js +34 -6
  40. package/lib/lazy-helper.d.ts +14 -0
  41. package/lib/lazy-helper.js +71 -0
  42. package/lib/locale/en-US.json +1 -0
  43. package/lib/locale/index.d.ts +2 -0
  44. package/lib/locale/zh-CN.json +1 -0
  45. package/lib/models/DisplayItemModel.d.ts +1 -1
  46. package/lib/models/EditableItemModel.d.ts +1 -1
  47. package/lib/models/FilterableItemModel.d.ts +1 -1
  48. package/lib/models/flowModel.d.ts +13 -10
  49. package/lib/models/flowModel.js +78 -18
  50. package/lib/provider.js +38 -23
  51. package/lib/reactive/observer.js +46 -16
  52. package/lib/runjs-context/registry.d.ts +1 -1
  53. package/lib/runjs-context/setup.js +20 -12
  54. package/lib/runjs-context/snippets/index.js +13 -2
  55. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.d.ts +11 -0
  56. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.js +50 -0
  57. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.d.ts +11 -0
  58. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.js +54 -0
  59. package/lib/scheduler/ModelOperationScheduler.d.ts +5 -1
  60. package/lib/scheduler/ModelOperationScheduler.js +3 -2
  61. package/lib/types.d.ts +47 -1
  62. package/lib/utils/createCollectionContextMeta.js +6 -2
  63. package/lib/utils/index.d.ts +2 -2
  64. package/lib/utils/index.js +4 -0
  65. package/lib/utils/parsePathnameToViewParams.js +1 -1
  66. package/lib/utils/runjsTemplateCompat.js +1 -1
  67. package/lib/utils/runjsValue.js +41 -11
  68. package/lib/utils/schema-utils.d.ts +7 -1
  69. package/lib/utils/schema-utils.js +19 -0
  70. package/lib/views/FlowView.d.ts +7 -1
  71. package/lib/views/runViewBeforeClose.d.ts +10 -0
  72. package/lib/views/runViewBeforeClose.js +45 -0
  73. package/lib/views/useDialog.d.ts +2 -1
  74. package/lib/views/useDialog.js +20 -3
  75. package/lib/views/useDrawer.d.ts +2 -1
  76. package/lib/views/useDrawer.js +20 -3
  77. package/lib/views/usePage.d.ts +2 -1
  78. package/lib/views/usePage.js +10 -3
  79. package/package.json +6 -5
  80. package/src/JSRunner.ts +68 -4
  81. package/src/ViewScopedFlowEngine.ts +4 -0
  82. package/src/__tests__/JSRunner.test.ts +27 -1
  83. package/src/__tests__/flow-engine.test.ts +166 -0
  84. package/src/__tests__/flowContext.test.ts +65 -1
  85. package/src/__tests__/flowEngine.modelLoaders.test.ts +245 -0
  86. package/src/__tests__/flowSettings.test.ts +94 -15
  87. package/src/__tests__/objectVariable.test.ts +24 -0
  88. package/src/__tests__/provider.test.tsx +24 -2
  89. package/src/__tests__/renderHiddenInConfig.test.tsx +6 -6
  90. package/src/__tests__/runjsContext.test.ts +16 -0
  91. package/src/__tests__/runjsContextRuntime.test.ts +2 -0
  92. package/src/__tests__/runjsPreprocessDefault.test.ts +23 -0
  93. package/src/__tests__/runjsSnippets.test.ts +21 -0
  94. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  95. package/src/components/FieldModelRenderer.tsx +2 -1
  96. package/src/components/FlowModelRenderer.tsx +18 -6
  97. package/src/components/MobilePopup.tsx +4 -2
  98. package/src/components/__tests__/FlowModelRenderer.test.tsx +65 -2
  99. package/src/components/__tests__/dnd.test.ts +44 -0
  100. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +20 -10
  101. package/src/components/__tests__/gridDragPlanner.test.ts +512 -3
  102. package/src/components/dnd/__tests__/DndProvider.test.tsx +98 -0
  103. package/src/components/dnd/gridDragPlanner.ts +743 -19
  104. package/src/components/dnd/index.tsx +291 -27
  105. package/src/components/settings/wrappers/component/SelectWithTitle.tsx +21 -9
  106. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +88 -10
  107. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +487 -440
  108. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +18 -2
  109. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +189 -3
  110. package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +778 -0
  111. package/src/components/settings/wrappers/contextual/useFloatToolbarPortal.ts +360 -0
  112. package/src/components/settings/wrappers/contextual/useFloatToolbarVisibility.ts +361 -0
  113. package/src/components/subModel/AddSubModelButton.tsx +32 -2
  114. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +142 -32
  115. package/src/components/subModel/index.ts +1 -0
  116. package/src/components/subModel/utils.ts +1 -1
  117. package/src/data-source/__tests__/index.test.ts +34 -1
  118. package/src/data-source/index.ts +258 -2
  119. package/src/executor/FlowExecutor.ts +34 -9
  120. package/src/executor/__tests__/flowExecutor.test.ts +57 -0
  121. package/src/flowContext.ts +37 -3
  122. package/src/flowEngine.ts +445 -11
  123. package/src/flowI18n.ts +2 -1
  124. package/src/flowSettings.ts +40 -6
  125. package/src/lazy-helper.tsx +57 -0
  126. package/src/locale/en-US.json +1 -0
  127. package/src/locale/zh-CN.json +1 -0
  128. package/src/models/DisplayItemModel.tsx +1 -1
  129. package/src/models/EditableItemModel.tsx +1 -1
  130. package/src/models/FilterableItemModel.tsx +1 -1
  131. package/src/models/__tests__/dispatchEvent.when.test.ts +214 -0
  132. package/src/models/__tests__/flowModel.test.ts +19 -3
  133. package/src/models/flowModel.tsx +119 -33
  134. package/src/provider.tsx +41 -25
  135. package/src/reactive/__tests__/observer.test.tsx +82 -0
  136. package/src/reactive/observer.tsx +87 -25
  137. package/src/runjs-context/registry.ts +1 -1
  138. package/src/runjs-context/setup.ts +22 -12
  139. package/src/runjs-context/snippets/index.ts +12 -1
  140. package/src/runjs-context/snippets/scene/detail/set-field-style.snippet.ts +30 -0
  141. package/src/runjs-context/snippets/scene/table/set-cell-style.snippet.ts +34 -0
  142. package/src/scheduler/ModelOperationScheduler.ts +14 -3
  143. package/src/types.ts +60 -0
  144. package/src/utils/__tests__/createCollectionContextMeta.test.ts +48 -0
  145. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +7 -0
  146. package/src/utils/__tests__/runjsValue.test.ts +11 -0
  147. package/src/utils/__tests__/utils.test.ts +62 -0
  148. package/src/utils/createCollectionContextMeta.ts +6 -2
  149. package/src/utils/index.ts +2 -1
  150. package/src/utils/parsePathnameToViewParams.ts +2 -2
  151. package/src/utils/runjsTemplateCompat.ts +1 -1
  152. package/src/utils/runjsValue.ts +50 -11
  153. package/src/utils/schema-utils.ts +30 -1
  154. package/src/views/FlowView.tsx +11 -1
  155. package/src/views/__tests__/runViewBeforeClose.test.ts +30 -0
  156. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +13 -12
  157. package/src/views/runViewBeforeClose.ts +19 -0
  158. package/src/views/useDialog.tsx +25 -3
  159. package/src/views/useDrawer.tsx +25 -3
  160. package/src/views/usePage.tsx +12 -3
@@ -126,6 +126,15 @@ const openStepSettingsDialog = /* @__PURE__ */ __name(async ({
126
126
  }
127
127
  };
128
128
  const openView = model.context.viewer[mode].bind(model.context.viewer);
129
+ const resolvedUiModeProps = (0, import_reactive.toJS)(uiModeProps) || {};
130
+ const { zIndex: uiModeZIndex, ...restUiModeProps } = resolvedUiModeProps;
131
+ const resolveDialogZIndex = /* @__PURE__ */ __name((rawZIndex) => {
132
+ var _a2, _b2;
133
+ const nextZIndex = typeof ((_a2 = model.context.viewer) == null ? void 0 : _a2.getNextZIndex) === "function" ? model.context.viewer.getNextZIndex() : (((_b2 = model.context.themeToken) == null ? void 0 : _b2.zIndexPopupBase) || 1e3) + 1;
134
+ const inputZIndex = Number(rawZIndex) || 0;
135
+ return Math.max(nextZIndex, inputZIndex);
136
+ }, "resolveDialogZIndex");
137
+ const mergedZIndex = resolveDialogZIndex(uiModeZIndex);
129
138
  const form = (0, import_core.createForm)({
130
139
  initialValues: (0, import_utils.compileUiSchema)(scopes, initialValues)
131
140
  });
@@ -141,7 +150,8 @@ const openStepSettingsDialog = /* @__PURE__ */ __name(async ({
141
150
  title: dialogTitle || t(title),
142
151
  width: dialogWidth,
143
152
  destroyOnClose: true,
144
- ...(0, import_reactive.toJS)(uiModeProps),
153
+ ...restUiModeProps,
154
+ zIndex: mergedZIndex,
145
155
  // 透传 navigation,便于变量元信息根据真实视图栈推断父级弹窗
146
156
  inputArgs,
147
157
  onClose: /* @__PURE__ */ __name(() => {
@@ -155,7 +165,11 @@ const openStepSettingsDialog = /* @__PURE__ */ __name(async ({
155
165
  (0, import_react2.useEffect)(() => {
156
166
  return (0, import_reactive.autorun)(() => {
157
167
  const dynamicProps = (0, import_reactive.toJS)(uiModeProps);
158
- currentDialog.update(dynamicProps);
168
+ const { zIndex, ...restDynamicProps } = dynamicProps || {};
169
+ currentDialog.update({
170
+ ...restDynamicProps,
171
+ zIndex: resolveDialogZIndex(zIndex)
172
+ });
159
173
  });
160
174
  }, []);
161
175
  const compiledFormSchema = (0, import_utils.compileUiSchema)(scopes, formSchema);
@@ -0,0 +1,36 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import type { CSSProperties, RefObject } from 'react';
10
+ type ToolbarPortalPositioningMode = 'fixed' | 'absolute';
11
+ export interface ToolbarPortalRenderSnapshot {
12
+ mountElement: HTMLElement;
13
+ positioningMode: ToolbarPortalPositioningMode;
14
+ }
15
+ export interface ToolbarPortalRect {
16
+ top: number;
17
+ left: number;
18
+ width: number;
19
+ height: number;
20
+ }
21
+ interface UseFloatToolbarPortalOptions {
22
+ active: boolean;
23
+ containerRef: RefObject<HTMLDivElement>;
24
+ toolbarContainerRef: RefObject<HTMLDivElement>;
25
+ toolbarStyle?: CSSProperties;
26
+ }
27
+ interface UseFloatToolbarPortalResult {
28
+ portalRect: ToolbarPortalRect;
29
+ portalRenderSnapshot: ToolbarPortalRenderSnapshot | null;
30
+ getPopupContainer: (triggerNode?: HTMLElement) => HTMLElement;
31
+ updatePortalRect: () => void;
32
+ schedulePortalRectUpdate: () => void;
33
+ }
34
+ export declare const omitToolbarPortalInsetStyle: (toolbarStyle?: CSSProperties) => CSSProperties | undefined;
35
+ export declare const useFloatToolbarPortal: ({ active, containerRef, toolbarContainerRef, toolbarStyle, }: UseFloatToolbarPortalOptions) => UseFloatToolbarPortalResult;
36
+ export {};
@@ -0,0 +1,274 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
18
+ };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
+ }
25
+ return to;
26
+ };
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var useFloatToolbarPortal_exports = {};
29
+ __export(useFloatToolbarPortal_exports, {
30
+ omitToolbarPortalInsetStyle: () => omitToolbarPortalInsetStyle,
31
+ useFloatToolbarPortal: () => useFloatToolbarPortal
32
+ });
33
+ module.exports = __toCommonJS(useFloatToolbarPortal_exports);
34
+ var import_react = require("react");
35
+ const APP_CONTAINER_SELECTOR = "#nocobase-app-container";
36
+ const MENU_SUBMENU_POPUP_SELECTOR = ".ant-menu-submenu-popup";
37
+ const DRAWER_CONTENT_WRAPPER_SELECTOR = ".ant-drawer-content-wrapper";
38
+ const DRAWER_CONTENT_SELECTOR = ".ant-drawer-content";
39
+ const DRAWER_ROOT_SELECTOR = ".ant-drawer-root";
40
+ const MODAL_SELECTOR = ".ant-modal";
41
+ const MODAL_WRAP_SELECTOR = ".ant-modal-wrap";
42
+ const MODAL_ROOT_SELECTOR = ".ant-modal-root";
43
+ const defaultPortalRect = {
44
+ top: 0,
45
+ left: 0,
46
+ width: 0,
47
+ height: 0
48
+ };
49
+ const getClosestElement = /* @__PURE__ */ __name((hostEl, selector) => hostEl == null ? void 0 : hostEl.closest(selector), "getClosestElement");
50
+ const createAbsolutePortalHostConfig = /* @__PURE__ */ __name((element) => ({
51
+ mountElement: element,
52
+ positioningElement: element,
53
+ positioningMode: "absolute"
54
+ }), "createAbsolutePortalHostConfig");
55
+ const popupPortalHostResolvers = [
56
+ (hostEl) => getClosestElement(hostEl, MENU_SUBMENU_POPUP_SELECTOR),
57
+ (hostEl) => getClosestElement(hostEl, DRAWER_CONTENT_WRAPPER_SELECTOR),
58
+ (hostEl) => getClosestElement(hostEl, MODAL_WRAP_SELECTOR),
59
+ (hostEl) => getClosestElement(hostEl, MODAL_SELECTOR),
60
+ (hostEl) => {
61
+ const drawerContent = getClosestElement(hostEl, DRAWER_CONTENT_SELECTOR);
62
+ return drawerContent ? getClosestElement(drawerContent, DRAWER_CONTENT_WRAPPER_SELECTOR) || drawerContent : null;
63
+ },
64
+ (hostEl) => getClosestElement(hostEl, DRAWER_ROOT_SELECTOR),
65
+ (hostEl) => getClosestElement(hostEl, MODAL_ROOT_SELECTOR)
66
+ ];
67
+ const getPopupPortalHostConfig = /* @__PURE__ */ __name((hostEl) => {
68
+ for (const resolveHost of popupPortalHostResolvers) {
69
+ const popupHost = resolveHost(hostEl);
70
+ if (popupHost) {
71
+ return createAbsolutePortalHostConfig(popupHost);
72
+ }
73
+ }
74
+ return null;
75
+ }, "getPopupPortalHostConfig");
76
+ const getToolbarPortalHostConfig = /* @__PURE__ */ __name((hostEl) => {
77
+ if (typeof document === "undefined") {
78
+ return null;
79
+ }
80
+ const popupRootConfig = getPopupPortalHostConfig(hostEl);
81
+ if (popupRootConfig) {
82
+ return popupRootConfig;
83
+ }
84
+ const appContainer = document.querySelector(APP_CONTAINER_SELECTOR);
85
+ if (appContainer) {
86
+ return createAbsolutePortalHostConfig(appContainer);
87
+ }
88
+ return {
89
+ mountElement: document.body,
90
+ positioningElement: document.body,
91
+ positioningMode: "fixed"
92
+ };
93
+ }, "getToolbarPortalHostConfig");
94
+ const parseToolbarInsetValue = /* @__PURE__ */ __name((value) => {
95
+ if (typeof value === "number" && Number.isFinite(value)) {
96
+ return value;
97
+ }
98
+ if (typeof value === "string") {
99
+ const trimmedValue = value.trim();
100
+ if (/^-?\d+(\.\d+)?(px)?$/.test(trimmedValue)) {
101
+ return Number.parseFloat(trimmedValue);
102
+ }
103
+ }
104
+ return 0;
105
+ }, "parseToolbarInsetValue");
106
+ const resolveToolbarPortalInset = /* @__PURE__ */ __name((toolbarStyle) => {
107
+ return {
108
+ top: parseToolbarInsetValue(toolbarStyle == null ? void 0 : toolbarStyle.top),
109
+ left: parseToolbarInsetValue(toolbarStyle == null ? void 0 : toolbarStyle.left),
110
+ right: parseToolbarInsetValue(toolbarStyle == null ? void 0 : toolbarStyle.right),
111
+ bottom: parseToolbarInsetValue(toolbarStyle == null ? void 0 : toolbarStyle.bottom)
112
+ };
113
+ }, "resolveToolbarPortalInset");
114
+ const getAbsolutePositioningElement = /* @__PURE__ */ __name((toolbarEl, portalHostConfig) => {
115
+ if (!portalHostConfig || portalHostConfig.positioningMode !== "absolute") {
116
+ return (portalHostConfig == null ? void 0 : portalHostConfig.positioningElement) || null;
117
+ }
118
+ const offsetParent = toolbarEl == null ? void 0 : toolbarEl.offsetParent;
119
+ if (offsetParent instanceof HTMLElement && offsetParent !== document.body && offsetParent !== document.documentElement) {
120
+ return offsetParent;
121
+ }
122
+ return portalHostConfig.positioningElement;
123
+ }, "getAbsolutePositioningElement");
124
+ const calculatePortalRect = /* @__PURE__ */ __name((hostEl, portalHostConfig, toolbarStyle, toolbarEl) => {
125
+ if (!hostEl) {
126
+ return defaultPortalRect;
127
+ }
128
+ const inset = resolveToolbarPortalInset(toolbarStyle);
129
+ const hostRect = hostEl.getBoundingClientRect();
130
+ let rect;
131
+ if (!portalHostConfig || portalHostConfig.positioningMode === "fixed") {
132
+ rect = {
133
+ top: hostRect.top,
134
+ left: hostRect.left,
135
+ width: hostRect.width,
136
+ height: hostRect.height
137
+ };
138
+ } else {
139
+ const positioningElement = getAbsolutePositioningElement(toolbarEl || null, portalHostConfig);
140
+ const portalHostRect = (positioningElement == null ? void 0 : positioningElement.getBoundingClientRect()) || portalHostConfig.positioningElement.getBoundingClientRect();
141
+ const scrollTop = (positioningElement == null ? void 0 : positioningElement.scrollTop) ?? portalHostConfig.positioningElement.scrollTop;
142
+ const scrollLeft = (positioningElement == null ? void 0 : positioningElement.scrollLeft) ?? portalHostConfig.positioningElement.scrollLeft;
143
+ rect = {
144
+ top: hostRect.top - portalHostRect.top + scrollTop,
145
+ left: hostRect.left - portalHostRect.left + scrollLeft,
146
+ width: hostRect.width,
147
+ height: hostRect.height
148
+ };
149
+ }
150
+ return {
151
+ top: rect.top + inset.top,
152
+ left: rect.left + inset.left,
153
+ width: Math.max(0, rect.width - inset.left - inset.right),
154
+ height: Math.max(0, rect.height - inset.top - inset.bottom)
155
+ };
156
+ }, "calculatePortalRect");
157
+ const omitToolbarPortalInsetStyle = /* @__PURE__ */ __name((toolbarStyle) => {
158
+ if (!toolbarStyle) {
159
+ return void 0;
160
+ }
161
+ const nextStyle = { ...toolbarStyle };
162
+ delete nextStyle.top;
163
+ delete nextStyle.left;
164
+ delete nextStyle.right;
165
+ delete nextStyle.bottom;
166
+ return nextStyle;
167
+ }, "omitToolbarPortalInsetStyle");
168
+ const useFloatToolbarPortal = /* @__PURE__ */ __name(({
169
+ active,
170
+ containerRef,
171
+ toolbarContainerRef,
172
+ toolbarStyle
173
+ }) => {
174
+ const [portalRect, setPortalRect] = (0, import_react.useState)(defaultPortalRect);
175
+ const [portalRenderSnapshot, setPortalRenderSnapshot] = (0, import_react.useState)(null);
176
+ const portalHostConfigRef = (0, import_react.useRef)(null);
177
+ const portalRafIdRef = (0, import_react.useRef)(null);
178
+ const updatePortalRect = (0, import_react.useCallback)(() => {
179
+ const hostElement = containerRef.current;
180
+ if (!hostElement) {
181
+ return;
182
+ }
183
+ const nextPortalHostConfig = getToolbarPortalHostConfig(hostElement);
184
+ portalHostConfigRef.current = nextPortalHostConfig;
185
+ setPortalRenderSnapshot((prevSnapshot) => {
186
+ if (!nextPortalHostConfig) {
187
+ return prevSnapshot === null ? prevSnapshot : null;
188
+ }
189
+ if ((prevSnapshot == null ? void 0 : prevSnapshot.mountElement) === nextPortalHostConfig.mountElement && (prevSnapshot == null ? void 0 : prevSnapshot.positioningMode) === nextPortalHostConfig.positioningMode) {
190
+ return prevSnapshot;
191
+ }
192
+ return {
193
+ mountElement: nextPortalHostConfig.mountElement,
194
+ positioningMode: nextPortalHostConfig.positioningMode
195
+ };
196
+ });
197
+ const nextRect = calculatePortalRect(hostElement, nextPortalHostConfig, toolbarStyle, toolbarContainerRef.current);
198
+ setPortalRect((prevRect) => {
199
+ if (prevRect.top === nextRect.top && prevRect.left === nextRect.left && prevRect.width === nextRect.width && prevRect.height === nextRect.height) {
200
+ return prevRect;
201
+ }
202
+ return nextRect;
203
+ });
204
+ }, [containerRef, toolbarContainerRef, toolbarStyle]);
205
+ const schedulePortalRectUpdate = (0, import_react.useCallback)(() => {
206
+ if (portalRafIdRef.current !== null) {
207
+ return;
208
+ }
209
+ portalRafIdRef.current = window.requestAnimationFrame(() => {
210
+ portalRafIdRef.current = null;
211
+ updatePortalRect();
212
+ });
213
+ }, [updatePortalRect]);
214
+ const getPopupContainer = (0, import_react.useCallback)(
215
+ (triggerNode) => {
216
+ var _a, _b, _c, _d, _e;
217
+ const fallbackContainer = ((_a = triggerNode == null ? void 0 : triggerNode.ownerDocument) == null ? void 0 : _a.body) || ((_c = (_b = containerRef.current) == null ? void 0 : _b.ownerDocument) == null ? void 0 : _c.body) || (typeof document !== "undefined" ? document.body : null);
218
+ return ((_d = portalHostConfigRef.current) == null ? void 0 : _d.mountElement) || ((_e = getToolbarPortalHostConfig(triggerNode || containerRef.current)) == null ? void 0 : _e.mountElement) || fallbackContainer;
219
+ },
220
+ [containerRef]
221
+ );
222
+ (0, import_react.useEffect)(() => {
223
+ var _a, _b;
224
+ if (!active) {
225
+ return;
226
+ }
227
+ updatePortalRect();
228
+ const handleViewportChange = /* @__PURE__ */ __name(() => {
229
+ schedulePortalRectUpdate();
230
+ }, "handleViewportChange");
231
+ const container = containerRef.current;
232
+ const mountElement = (_a = portalHostConfigRef.current) == null ? void 0 : _a.mountElement;
233
+ const positioningElement = (_b = portalHostConfigRef.current) == null ? void 0 : _b.positioningElement;
234
+ const resizeObserver = typeof ResizeObserver !== "undefined" && container ? new ResizeObserver(() => {
235
+ schedulePortalRectUpdate();
236
+ }) : null;
237
+ if (container) {
238
+ resizeObserver == null ? void 0 : resizeObserver.observe(container);
239
+ }
240
+ if (mountElement && mountElement !== container) {
241
+ resizeObserver == null ? void 0 : resizeObserver.observe(mountElement);
242
+ }
243
+ if (positioningElement && positioningElement !== container && positioningElement !== mountElement) {
244
+ resizeObserver == null ? void 0 : resizeObserver.observe(positioningElement);
245
+ }
246
+ window.addEventListener("resize", handleViewportChange);
247
+ window.addEventListener("scroll", handleViewportChange, true);
248
+ return () => {
249
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
250
+ window.removeEventListener("resize", handleViewportChange);
251
+ window.removeEventListener("scroll", handleViewportChange, true);
252
+ };
253
+ }, [active, containerRef, schedulePortalRectUpdate, updatePortalRect]);
254
+ (0, import_react.useEffect)(() => {
255
+ return () => {
256
+ if (portalRafIdRef.current !== null) {
257
+ window.cancelAnimationFrame(portalRafIdRef.current);
258
+ }
259
+ portalHostConfigRef.current = null;
260
+ };
261
+ }, []);
262
+ return {
263
+ portalRect,
264
+ portalRenderSnapshot,
265
+ getPopupContainer,
266
+ updatePortalRect,
267
+ schedulePortalRectUpdate
268
+ };
269
+ }, "useFloatToolbarPortal");
270
+ // Annotate the CommonJS export names for ESM import in node:
271
+ 0 && (module.exports = {
272
+ omitToolbarPortalInsetStyle,
273
+ useFloatToolbarPortal
274
+ });
@@ -0,0 +1,30 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import type { MouseEvent as ReactMouseEvent, RefObject } from 'react';
10
+ interface UseFloatToolbarVisibilityOptions {
11
+ modelUid: string;
12
+ containerRef: RefObject<HTMLDivElement>;
13
+ toolbarContainerRef: RefObject<HTMLDivElement>;
14
+ updatePortalRect: () => void;
15
+ schedulePortalRectUpdate: () => void;
16
+ }
17
+ interface UseFloatToolbarVisibilityResult {
18
+ isToolbarVisible: boolean;
19
+ shouldRenderToolbar: boolean;
20
+ handleSettingsMenuOpenChange: (open: boolean) => void;
21
+ handleChildHover: (e: ReactMouseEvent) => void;
22
+ handleHostMouseEnter: () => void;
23
+ handleHostMouseLeave: (e: ReactMouseEvent<HTMLDivElement>) => void;
24
+ handleToolbarMouseEnter: () => void;
25
+ handleToolbarMouseLeave: (e: ReactMouseEvent<HTMLDivElement>) => void;
26
+ handleResizeDragStart: () => void;
27
+ handleResizeDragEnd: () => void;
28
+ }
29
+ export declare const useFloatToolbarVisibility: ({ modelUid, containerRef, toolbarContainerRef, updatePortalRect, schedulePortalRectUpdate, }: UseFloatToolbarVisibilityOptions) => UseFloatToolbarVisibilityResult;
30
+ export {};