@nocobase/flow-engine 2.1.0-alpha.40 → 2.1.0-alpha.46

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 (77) hide show
  1. package/lib/FlowContextProvider.d.ts +5 -1
  2. package/lib/FlowContextProvider.js +9 -2
  3. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +84 -32
  4. package/lib/components/subModel/LazyDropdown.js +208 -16
  5. package/lib/components/subModel/utils.d.ts +1 -0
  6. package/lib/components/subModel/utils.js +6 -2
  7. package/lib/data-source/index.d.ts +9 -0
  8. package/lib/data-source/index.js +12 -0
  9. package/lib/executor/FlowExecutor.js +0 -3
  10. package/lib/flowContext.d.ts +6 -1
  11. package/lib/flowContext.js +38 -6
  12. package/lib/flowEngine.d.ts +4 -3
  13. package/lib/flowEngine.js +72 -40
  14. package/lib/models/flowModel.js +48 -16
  15. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +4 -3
  16. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +4 -15
  17. package/lib/runjs-context/contexts/JSColumnRunJSContext.js +5 -2
  18. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +5 -8
  19. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +4 -3
  20. package/lib/runjs-context/contexts/JSItemRunJSContext.js +4 -3
  21. package/lib/runjs-context/contexts/base.js +464 -29
  22. package/lib/runjs-context/contexts/elementDoc.d.ts +11 -0
  23. package/lib/runjs-context/contexts/elementDoc.js +152 -0
  24. package/lib/utils/loadedPageCache.d.ts +24 -0
  25. package/lib/utils/loadedPageCache.js +139 -0
  26. package/lib/utils/parsePathnameToViewParams.d.ts +5 -1
  27. package/lib/utils/parsePathnameToViewParams.js +28 -4
  28. package/lib/views/ViewNavigation.d.ts +12 -2
  29. package/lib/views/ViewNavigation.js +22 -7
  30. package/lib/views/createViewMeta.js +114 -50
  31. package/lib/views/inheritLayoutContext.d.ts +10 -0
  32. package/lib/views/inheritLayoutContext.js +50 -0
  33. package/lib/views/useDialog.js +2 -0
  34. package/lib/views/useDrawer.js +2 -0
  35. package/lib/views/usePage.js +2 -0
  36. package/package.json +4 -4
  37. package/src/FlowContextProvider.tsx +9 -1
  38. package/src/__tests__/createViewMeta.popup.test.ts +115 -1
  39. package/src/__tests__/flowContext.test.ts +23 -0
  40. package/src/__tests__/flowEngine.moveModel.test.ts +81 -1
  41. package/src/__tests__/flowEngine.removeModel.test.ts +47 -3
  42. package/src/__tests__/runjsContext.test.ts +18 -0
  43. package/src/__tests__/runjsContextImplementations.test.ts +9 -2
  44. package/src/__tests__/runjsLocales.test.ts +6 -5
  45. package/src/__tests__/viewScopedFlowEngine.test.ts +133 -0
  46. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +90 -38
  47. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +155 -5
  48. package/src/components/subModel/LazyDropdown.tsx +237 -16
  49. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +254 -1
  50. package/src/components/subModel/utils.ts +6 -1
  51. package/src/data-source/index.ts +18 -0
  52. package/src/executor/FlowExecutor.ts +0 -3
  53. package/src/executor/__tests__/flowExecutor.test.ts +26 -0
  54. package/src/flowContext.ts +43 -6
  55. package/src/flowEngine.ts +75 -38
  56. package/src/models/__tests__/flowEngine.resolveUse.test.ts +0 -15
  57. package/src/models/__tests__/flowModel.test.ts +46 -62
  58. package/src/models/flowModel.tsx +65 -32
  59. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +4 -3
  60. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +4 -15
  61. package/src/runjs-context/contexts/JSColumnRunJSContext.ts +4 -2
  62. package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +5 -9
  63. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +4 -3
  64. package/src/runjs-context/contexts/JSItemRunJSContext.ts +4 -3
  65. package/src/runjs-context/contexts/base.ts +467 -31
  66. package/src/runjs-context/contexts/elementDoc.ts +130 -0
  67. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +21 -0
  68. package/src/utils/loadedPageCache.ts +147 -0
  69. package/src/utils/parsePathnameToViewParams.ts +45 -5
  70. package/src/views/ViewNavigation.ts +40 -7
  71. package/src/views/__tests__/ViewNavigation.test.ts +52 -0
  72. package/src/views/__tests__/inheritLayoutContext.test.ts +53 -0
  73. package/src/views/createViewMeta.ts +106 -34
  74. package/src/views/inheritLayoutContext.ts +26 -0
  75. package/src/views/useDialog.tsx +2 -0
  76. package/src/views/useDrawer.tsx +2 -0
  77. package/src/views/usePage.tsx +2 -0
@@ -0,0 +1,152 @@
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 elementDoc_exports = {};
29
+ __export(elementDoc_exports, {
30
+ createElementPropertyDoc: () => createElementPropertyDoc,
31
+ createZhCNElementPropertyDoc: () => createZhCNElementPropertyDoc
32
+ });
33
+ module.exports = __toCommonJS(elementDoc_exports);
34
+ const elementProperties = {
35
+ innerHTML: "Sanitized inner HTML string.",
36
+ outerHTML: "Sanitized outer HTML string.",
37
+ textContent: "Text content.",
38
+ style: "Inline style declaration.",
39
+ classList: "DOMTokenList for CSS classes.",
40
+ appendChild: {
41
+ type: "function",
42
+ description: "Append a DOM node or text.",
43
+ detail: "(child: Node | string) => void",
44
+ completion: { insertText: `ctx.element.appendChild('text')` }
45
+ },
46
+ setAttribute: {
47
+ type: "function",
48
+ description: "Set an HTML attribute.",
49
+ detail: "(name: string, value: string) => void",
50
+ completion: { insertText: `ctx.element.setAttribute('data-key', 'value')` }
51
+ },
52
+ getAttribute: {
53
+ type: "function",
54
+ description: "Read an HTML attribute.",
55
+ detail: "(name: string) => string | null",
56
+ completion: { insertText: `ctx.element.getAttribute('data-key')` }
57
+ },
58
+ querySelector: {
59
+ type: "function",
60
+ description: "Find the first matching descendant.",
61
+ detail: "(selectors: string) => Element | null",
62
+ completion: { insertText: `ctx.element.querySelector('.selector')` }
63
+ },
64
+ querySelectorAll: {
65
+ type: "function",
66
+ description: "Find all matching descendants.",
67
+ detail: "(selectors: string) => NodeListOf<Element>",
68
+ completion: { insertText: `ctx.element.querySelectorAll('.selector')` }
69
+ },
70
+ addEventListener: {
71
+ type: "function",
72
+ description: "Attach an event listener to the element.",
73
+ detail: "(type: string, listener: EventListener) => void",
74
+ completion: { insertText: `ctx.element.addEventListener('click', (event) => {})` }
75
+ },
76
+ removeEventListener: {
77
+ type: "function",
78
+ description: "Remove an event listener from the element.",
79
+ detail: "(type: string, listener: EventListener) => void",
80
+ completion: { insertText: `ctx.element.removeEventListener('click', handler)` }
81
+ }
82
+ };
83
+ const zhCNElementProperties = {
84
+ innerHTML: "\u5DF2\u6D88\u6BD2\u7684 innerHTML \u5B57\u7B26\u4E32\u3002",
85
+ outerHTML: "\u5DF2\u6D88\u6BD2\u7684 outerHTML \u5B57\u7B26\u4E32\u3002",
86
+ textContent: "\u6587\u672C\u5185\u5BB9\u3002",
87
+ style: "\u5185\u8054\u6837\u5F0F\u58F0\u660E\u3002",
88
+ classList: "CSS class \u5217\u8868\u3002",
89
+ appendChild: {
90
+ type: "function",
91
+ description: "\u8FFD\u52A0 DOM \u8282\u70B9\u6216\u6587\u672C\u3002",
92
+ detail: "(child: Node | string) => void",
93
+ completion: { insertText: `ctx.element.appendChild('text')` }
94
+ },
95
+ setAttribute: {
96
+ type: "function",
97
+ description: "\u8BBE\u7F6E HTML \u5C5E\u6027\u3002",
98
+ detail: "(name: string, value: string) => void",
99
+ completion: { insertText: `ctx.element.setAttribute('data-key', 'value')` }
100
+ },
101
+ getAttribute: {
102
+ type: "function",
103
+ description: "\u8BFB\u53D6 HTML \u5C5E\u6027\u3002",
104
+ detail: "(name: string) => string | null",
105
+ completion: { insertText: `ctx.element.getAttribute('data-key')` }
106
+ },
107
+ querySelector: {
108
+ type: "function",
109
+ description: "\u67E5\u8BE2\u7B2C\u4E00\u4E2A\u5339\u914D\u7684\u540E\u4EE3\u5143\u7D20\u3002",
110
+ detail: "(selectors: string) => Element | null",
111
+ completion: { insertText: `ctx.element.querySelector('.selector')` }
112
+ },
113
+ querySelectorAll: {
114
+ type: "function",
115
+ description: "\u67E5\u8BE2\u6240\u6709\u5339\u914D\u7684\u540E\u4EE3\u5143\u7D20\u3002",
116
+ detail: "(selectors: string) => NodeListOf<Element>",
117
+ completion: { insertText: `ctx.element.querySelectorAll('.selector')` }
118
+ },
119
+ addEventListener: {
120
+ type: "function",
121
+ description: "\u7ED9\u5143\u7D20\u6DFB\u52A0\u4E8B\u4EF6\u76D1\u542C\u3002",
122
+ detail: "(type: string, listener: EventListener) => void",
123
+ completion: { insertText: `ctx.element.addEventListener('click', (event) => {})` }
124
+ },
125
+ removeEventListener: {
126
+ type: "function",
127
+ description: "\u79FB\u9664\u5143\u7D20\u4E8B\u4EF6\u76D1\u542C\u3002",
128
+ detail: "(type: string, listener: EventListener) => void",
129
+ completion: { insertText: `ctx.element.removeEventListener('click', handler)` }
130
+ }
131
+ };
132
+ function createElementPropertyDoc(description = "Current DOM container for this RunJS context. Usually an ElementProxy.") {
133
+ return {
134
+ description,
135
+ detail: "HTMLElement | ElementProxy",
136
+ properties: elementProperties
137
+ };
138
+ }
139
+ __name(createElementPropertyDoc, "createElementPropertyDoc");
140
+ function createZhCNElementPropertyDoc(description = "\u5F53\u524D RunJS \u4E0A\u4E0B\u6587\u7684 DOM \u5BB9\u5668\uFF0C\u901A\u5E38\u4E3A ElementProxy\u3002") {
141
+ return {
142
+ description,
143
+ detail: "HTMLElement | ElementProxy",
144
+ properties: zhCNElementProperties
145
+ };
146
+ }
147
+ __name(createZhCNElementPropertyDoc, "createZhCNElementPropertyDoc");
148
+ // Annotate the CommonJS export names for ESM import in node:
149
+ 0 && (module.exports = {
150
+ createElementPropertyDoc,
151
+ createZhCNElementPropertyDoc
152
+ });
@@ -0,0 +1,24 @@
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 { FlowModel } from '../models';
10
+ type LoadedPageOptions = {
11
+ parentId?: string;
12
+ subKey?: string;
13
+ };
14
+ type DirtyKeyOptions = {
15
+ force?: boolean;
16
+ };
17
+ export declare const createLoadedPageCache: () => {
18
+ getDirtyKeyForModel(model?: FlowModel | null, options?: DirtyKeyOptions): string | undefined;
19
+ markDirty(key?: string): void;
20
+ shouldBypass(options?: LoadedPageOptions, isFlowSettingsEnabled?: () => boolean): boolean;
21
+ clear(options?: LoadedPageOptions): void;
22
+ mountModelToParent: <T extends FlowModel<import("..").DefaultStructure> = FlowModel<import("..").DefaultStructure>>(model: T, forceReplace?: boolean) => T;
23
+ };
24
+ export {};
@@ -0,0 +1,139 @@
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 loadedPageCache_exports = {};
29
+ __export(loadedPageCache_exports, {
30
+ createLoadedPageCache: () => createLoadedPageCache
31
+ });
32
+ module.exports = __toCommonJS(loadedPageCache_exports);
33
+ const getLoadedPageKey = /* @__PURE__ */ __name((options) => {
34
+ const parentId = options == null ? void 0 : options.parentId;
35
+ const subKey = options == null ? void 0 : options.subKey;
36
+ if (!parentId || subKey !== "page") {
37
+ return void 0;
38
+ }
39
+ return `${parentId}::${subKey}`;
40
+ }, "getLoadedPageKey");
41
+ const getLoadedPageKeyFromModel = /* @__PURE__ */ __name((model) => {
42
+ var _a;
43
+ let current = model;
44
+ while (current) {
45
+ if (current.subKey === "page" && ((_a = current.parent) == null ? void 0 : _a.uid)) {
46
+ return getLoadedPageKey({ parentId: current.parent.uid, subKey: current.subKey });
47
+ }
48
+ current = current.parent;
49
+ }
50
+ return void 0;
51
+ }, "getLoadedPageKeyFromModel");
52
+ const isFlowSettingsEnabledForContext = /* @__PURE__ */ __name((context) => {
53
+ try {
54
+ return !!(context == null ? void 0 : context.flowSettingsEnabled);
55
+ } catch (error) {
56
+ return false;
57
+ }
58
+ }, "isFlowSettingsEnabledForContext");
59
+ const isFlowSettingsEnabledForModel = /* @__PURE__ */ __name((model) => {
60
+ if (isFlowSettingsEnabledForContext(model == null ? void 0 : model.context)) {
61
+ return true;
62
+ }
63
+ const visited = /* @__PURE__ */ new Set();
64
+ let engine = model == null ? void 0 : model.flowEngine;
65
+ while (engine && !visited.has(engine)) {
66
+ visited.add(engine);
67
+ if (isFlowSettingsEnabledForContext(engine.context)) {
68
+ return true;
69
+ }
70
+ engine = engine.previousEngine;
71
+ }
72
+ return false;
73
+ }, "isFlowSettingsEnabledForModel");
74
+ const removeLoadedModelTree = /* @__PURE__ */ __name((model) => {
75
+ if (!(model == null ? void 0 : model.uid) || !model.flowEngine) {
76
+ return;
77
+ }
78
+ if (model.flowEngine.getModel(model.uid) === model) {
79
+ model.flowEngine.removeModelWithSubModels(model.uid);
80
+ }
81
+ }, "removeLoadedModelTree");
82
+ const mountLoadedModelToParent = /* @__PURE__ */ __name((model, forceReplace = false) => {
83
+ var _a;
84
+ if (!(model == null ? void 0 : model.parent) || !model.subKey) {
85
+ return model;
86
+ }
87
+ const mounted = (_a = model.parent.subModels) == null ? void 0 : _a[model.subKey];
88
+ const existing = forceReplace && model.subType !== "array" && mounted && !Array.isArray(mounted) ? mounted : model.parent.findSubModel(model.subKey, (m) => m.uid === model.uid);
89
+ if (existing) {
90
+ if (!forceReplace || existing === model) {
91
+ return model;
92
+ }
93
+ removeLoadedModelTree(existing);
94
+ }
95
+ if (model.subType === "array") {
96
+ model.parent.addSubModel(model.subKey, model);
97
+ } else {
98
+ model.parent.setSubModel(model.subKey, model);
99
+ }
100
+ return model;
101
+ }, "mountLoadedModelToParent");
102
+ const createLoadedPageCache = /* @__PURE__ */ __name(() => {
103
+ const dirtyKeys = /* @__PURE__ */ new Set();
104
+ return {
105
+ getDirtyKeyForModel(model, options) {
106
+ if (!(options == null ? void 0 : options.force) && !isFlowSettingsEnabledForModel(model)) {
107
+ return void 0;
108
+ }
109
+ return getLoadedPageKeyFromModel(model);
110
+ },
111
+ markDirty(key) {
112
+ if (key) {
113
+ dirtyKeys.add(key);
114
+ }
115
+ },
116
+ shouldBypass(options, isFlowSettingsEnabled) {
117
+ const key = getLoadedPageKey(options);
118
+ if (!key || !dirtyKeys.has(key)) {
119
+ return false;
120
+ }
121
+ try {
122
+ return !(isFlowSettingsEnabled == null ? void 0 : isFlowSettingsEnabled());
123
+ } catch (error) {
124
+ return true;
125
+ }
126
+ },
127
+ clear(options) {
128
+ const key = getLoadedPageKey(options);
129
+ if (key) {
130
+ dirtyKeys.delete(key);
131
+ }
132
+ },
133
+ mountModelToParent: mountLoadedModelToParent
134
+ };
135
+ }, "createLoadedPageCache");
136
+ // Annotate the CommonJS export names for ESM import in node:
137
+ 0 && (module.exports = {
138
+ createLoadedPageCache
139
+ });
@@ -16,6 +16,10 @@ export interface ViewParam {
16
16
  /** source Id */
17
17
  sourceId?: string;
18
18
  }
19
+ export interface ParsePathnameToViewParamsOptions {
20
+ rootPrefix?: string;
21
+ basePath?: string;
22
+ }
19
23
  /**
20
24
  * 解析路径名为视图参数数组
21
25
  *
@@ -31,4 +35,4 @@ export interface ViewParam {
31
35
  * parsePathnameToViewParams('/admin/xxx/view/yyy') // [{ viewUid: 'xxx' }, { viewUid: 'yyy' }]
32
36
  * ```
33
37
  */
34
- export declare const parsePathnameToViewParams: (pathname: string) => ViewParam[];
38
+ export declare const parsePathnameToViewParams: (pathname: string, options?: ParsePathnameToViewParamsOptions) => ViewParam[];
@@ -30,20 +30,44 @@ __export(parsePathnameToViewParams_exports, {
30
30
  parsePathnameToViewParams: () => parsePathnameToViewParams
31
31
  });
32
32
  module.exports = __toCommonJS(parsePathnameToViewParams_exports);
33
- const parsePathnameToViewParams = /* @__PURE__ */ __name((pathname) => {
33
+ const normalizePathname = /* @__PURE__ */ __name((pathname) => {
34
+ if (!pathname || pathname === "/") {
35
+ return "/";
36
+ }
37
+ return `/${pathname.replace(/^\/+/, "").replace(/\/+$/, "")}`;
38
+ }, "normalizePathname");
39
+ const normalizeBasePath = /* @__PURE__ */ __name((basePath) => `/${basePath.replace(/^\/+/, "").replace(/\/+$/, "")}`, "normalizeBasePath");
40
+ const stripBasePath = /* @__PURE__ */ __name((pathname, basePath) => {
41
+ const normalizedPathname = normalizePathname(pathname);
42
+ const normalizedBasePath = normalizeBasePath(basePath);
43
+ if (normalizedPathname === normalizedBasePath) {
44
+ return "";
45
+ }
46
+ if (normalizedPathname.startsWith(`${normalizedBasePath}/`)) {
47
+ return normalizedPathname.slice(normalizedBasePath.length + 1);
48
+ }
49
+ return "";
50
+ }, "stripBasePath");
51
+ const parsePathnameToViewParams = /* @__PURE__ */ __name((pathname, options = {}) => {
34
52
  if (!pathname || pathname === "/") {
35
53
  return [];
36
54
  }
37
- const segments = pathname.replace(/^\/+/, "").split("/").filter(Boolean);
38
- if (segments.length < 2) {
55
+ const rootPrefix = options.rootPrefix || "admin";
56
+ const relativePath = options.basePath ? stripBasePath(pathname, options.basePath) : "";
57
+ const segments = (options.basePath ? relativePath : pathname).replace(/^\/+/, "").split("/").filter(Boolean);
58
+ if (segments.length < (options.basePath ? 1 : 2)) {
39
59
  return [];
40
60
  }
41
61
  const result = [];
42
62
  let currentView = null;
43
63
  let i = 0;
64
+ if (options.basePath) {
65
+ currentView = { viewUid: segments[0] };
66
+ i = 1;
67
+ }
44
68
  while (i < segments.length) {
45
69
  const segment = segments[i];
46
- if (segment === "admin" || segment === "view") {
70
+ if (segment === rootPrefix || segment === "view") {
47
71
  if (currentView) {
48
72
  result.push(currentView);
49
73
  }
@@ -11,6 +11,14 @@ import { ViewParam as SharedViewParam } from '../utils';
11
11
  type ViewParams = Omit<SharedViewParam, 'viewUid'> & {
12
12
  viewUid?: string;
13
13
  };
14
+ export interface GeneratePathnameFromViewParamsOptions {
15
+ prefix?: string;
16
+ basePath?: string;
17
+ }
18
+ export interface ViewNavigationOptions {
19
+ basePath?: string;
20
+ layoutBasePath?: string;
21
+ }
14
22
  /**
15
23
  * 将 ViewParam 数组转换为 pathname
16
24
  *
@@ -24,12 +32,13 @@ type ViewParams = Omit<SharedViewParam, 'viewUid'> & {
24
32
  * generatePathnameFromViewParams([{ viewUid: 'xxx' }, { viewUid: 'yyy' }]) // '/admin/xxx/view/yyy'
25
33
  * ```
26
34
  */
27
- export declare function generatePathnameFromViewParams(viewParams: ViewParams[]): string;
35
+ export declare function generatePathnameFromViewParams(viewParams: ViewParams[], options?: GeneratePathnameFromViewParamsOptions): string;
28
36
  export declare class ViewNavigation {
29
37
  viewStack: ReadonlyArray<ViewParams>;
30
38
  ctx: FlowEngineContext;
31
39
  viewParams: ViewParams;
32
- constructor(ctx: FlowEngineContext, viewParams: ViewParams[]);
40
+ private readonly basePath?;
41
+ constructor(ctx: FlowEngineContext, viewParams: ViewParams[], options?: ViewNavigationOptions);
33
42
  setViewStack(viewParams: ViewParams[]): void;
34
43
  changeTo(viewParam: ViewParams): void;
35
44
  navigateTo(viewParam: ViewParams, opts?: {
@@ -37,5 +46,6 @@ export declare class ViewNavigation {
37
46
  state?: any;
38
47
  }): void;
39
48
  back(): void;
49
+ private getLayoutBasePath;
40
50
  }
41
51
  export {};
@@ -47,11 +47,17 @@ function hasUsableSourceId(sourceId) {
47
47
  return sourceId !== void 0 && sourceId !== null && String(sourceId) !== "";
48
48
  }
49
49
  __name(hasUsableSourceId, "hasUsableSourceId");
50
- function generatePathnameFromViewParams(viewParams) {
50
+ function normalizeBasePath(basePath) {
51
+ const value = basePath || "/admin";
52
+ return `/${value.replace(/^\/+/, "").replace(/\/+$/, "")}`;
53
+ }
54
+ __name(normalizeBasePath, "normalizeBasePath");
55
+ function generatePathnameFromViewParams(viewParams, options = {}) {
56
+ const basePath = normalizeBasePath(options.basePath || options.prefix);
51
57
  if (!viewParams || viewParams.length === 0) {
52
- return "/admin";
58
+ return basePath;
53
59
  }
54
- const segments = ["admin"];
60
+ const segments = basePath.replace(/^\/+/, "").split("/").filter(Boolean);
55
61
  viewParams.forEach((viewParam, index) => {
56
62
  if (index > 0) {
57
63
  segments.push("view");
@@ -78,9 +84,11 @@ const _ViewNavigation = class _ViewNavigation {
78
84
  // 只能通过 setViewStack 修改
79
85
  ctx;
80
86
  viewParams;
81
- constructor(ctx, viewParams) {
87
+ basePath;
88
+ constructor(ctx, viewParams, options = {}) {
82
89
  this.setViewStack(viewParams);
83
90
  this.ctx = ctx;
91
+ this.basePath = options.basePath || options.layoutBasePath;
84
92
  (0, import_reactive.define)(this, {
85
93
  viewParams: import_reactive.observable
86
94
  });
@@ -96,19 +104,26 @@ const _ViewNavigation = class _ViewNavigation {
96
104
  }
97
105
  return { ...item };
98
106
  });
99
- const newPathname = generatePathnameFromViewParams(newViewStack);
107
+ const newPathname = generatePathnameFromViewParams(newViewStack, { basePath: this.getLayoutBasePath() });
100
108
  this.ctx.router.navigate(newPathname, { replace: true });
101
109
  }
102
110
  navigateTo(viewParam, opts) {
103
- const newViewPathname = generatePathnameFromViewParams([...this.viewStack, viewParam]);
111
+ const newViewPathname = generatePathnameFromViewParams([...this.viewStack, viewParam], {
112
+ basePath: this.getLayoutBasePath()
113
+ });
104
114
  const newPathname = newViewPathname;
105
115
  this.ctx.router.navigate(newPathname, opts);
106
116
  }
107
117
  back() {
108
118
  const prevStack = this.viewStack.slice(0, -1);
109
- const prevPath = generatePathnameFromViewParams(prevStack);
119
+ const prevPath = generatePathnameFromViewParams(prevStack, { basePath: this.getLayoutBasePath() });
110
120
  this.ctx.router.navigate(prevPath, { replace: true });
111
121
  }
122
+ getLayoutBasePath() {
123
+ var _a, _b;
124
+ const routePath = (_a = this.ctx.layout) == null ? void 0 : _a.routePath;
125
+ return this.basePath || ((_b = this.ctx.layoutRoute) == null ? void 0 : _b.basePathname) || ((routePath == null ? void 0 : routePath.startsWith("/")) ? routePath : "/admin");
126
+ }
112
127
  };
113
128
  __name(_ViewNavigation, "ViewNavigation");
114
129
  let ViewNavigation = _ViewNavigation;