@zk-tech/base-ui-configuration-service 0.0.1-alpha.1

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.
package/dist/index.js ADDED
@@ -0,0 +1,937 @@
1
+ import { Disposable } from '@zk-tech/bedrock/dispose';
2
+ import { IContainerService } from '@zk-tech/bedrock/di';
3
+ import { Emitter } from '@zk-tech/bedrock/event';
4
+ import { lvAssertNotHere, lvAssert, lvAssertNotNil, lvAssertNever } from '@zk-tech/bedrock/assert';
5
+ import { useSnapshot, proxy, snapshot } from 'valtio';
6
+ import { merge } from 'lodash-es';
7
+ import React3, { createContext, memo, useRef, startTransition, Suspense, useContext, useMemo, useEffect, useLayoutEffect, useState } from 'react';
8
+ import { SharedMutex } from '@zk-tech/bedrock/lock';
9
+ import { matchPath, useLocation, useNavigate, Route, Routes, Navigate, useOutlet, createPath, parsePath } from 'react-router-dom';
10
+ export { Navigate, matchPath, parsePath, resolvePath, useLocation, useSearchParams } from 'react-router-dom';
11
+ import { compile } from 'path-to-regexp';
12
+ import { ErrorBoundary as ErrorBoundary$1 } from 'react-error-boundary';
13
+ import { useMemoizedFn } from 'ahooks';
14
+ import cs from 'classnames';
15
+
16
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
17
+ var __decorateClass = (decorators, target, key, kind) => {
18
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
19
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
20
+ if (decorator = decorators[i])
21
+ result = (decorator(result)) || result;
22
+ return result;
23
+ };
24
+ var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
25
+
26
+ // src/base/middleware/action-point-runner.ts
27
+ var ActionPointRunner = class extends Function {
28
+ constructor(middlewares, point, _uiConfig) {
29
+ super();
30
+ this.middlewares = middlewares;
31
+ this.point = point;
32
+ this._uiConfig = _uiConfig;
33
+ this._isStop = false;
34
+ this.index = 0;
35
+ const closure = (...args) => closure.run(...args);
36
+ closure.middlewares = middlewares;
37
+ closure.point = point ?? {
38
+ name: "",
39
+ from: "",
40
+ trigger: "",
41
+ path: []
42
+ };
43
+ closure._uiConfig = _uiConfig;
44
+ return Object.setPrototypeOf(closure, new.target.prototype);
45
+ }
46
+ get isStop() {
47
+ return this._isStop;
48
+ }
49
+ run(...args) {
50
+ this._rawArguments = args;
51
+ this.index = -1;
52
+ let data;
53
+ while (this.hasNext() && !this._isStop) {
54
+ data = this.getNext()();
55
+ }
56
+ return data;
57
+ }
58
+ hasNext() {
59
+ return this.index < this.middlewares.length - 1;
60
+ }
61
+ getNext(skip = false) {
62
+ let next = () => {
63
+ };
64
+ if (this.hasNext()) {
65
+ this.index += 1;
66
+ const handler = this.middlewares[this.index];
67
+ next = () => {
68
+ return handler({
69
+ stop: () => {
70
+ this._isStop = true;
71
+ },
72
+ uiConfig: this._uiConfig,
73
+ actionInfo: this.point,
74
+ triggerArgs: this._rawArguments
75
+ });
76
+ };
77
+ }
78
+ return next;
79
+ }
80
+ };
81
+
82
+ // src/base/middleware/middleware.ts
83
+ var MiddlewareManager = class {
84
+ constructor() {
85
+ this._registerById = /* @__PURE__ */ new Map();
86
+ /** caller <-> middleware handler 的映射表 */
87
+ this._registerByCaller = /* @__PURE__ */ new Map();
88
+ this._onMiddlewareChange = new Emitter();
89
+ this._disposeMap = /* @__PURE__ */ new Map();
90
+ this.onMiddlewareChange = this._onMiddlewareChange.event;
91
+ }
92
+ buildRunner(options) {
93
+ const caller = this._getCaller(options);
94
+ const handlers = (this._registerByCaller.get(caller) ?? []).map((id) => this._registerById.get(id)?.handler).filter((item) => item);
95
+ if (options.handler) {
96
+ handlers.push(options.handler);
97
+ }
98
+ return new ActionPointRunner(
99
+ // @ts-ignore type error
100
+ handlers,
101
+ {
102
+ from: options.trigger,
103
+ name: options.uiConfig.id,
104
+ trigger: options.method
105
+ },
106
+ options.uiConfig
107
+ );
108
+ }
109
+ use(props) {
110
+ const existed = this._registerById.get(props.id);
111
+ if (existed) {
112
+ lvAssertNotHere("config had been existed");
113
+ }
114
+ this._registerById.set(props.id, props);
115
+ props.triggerMethod.forEach((item) => {
116
+ const caller = this._getCaller({ trigger: props.trigger, method: item });
117
+ if (!this._registerByCaller.has(caller)) {
118
+ this._registerByCaller.set(caller, []);
119
+ }
120
+ const target = this._registerByCaller.get(caller);
121
+ target.push(props.id);
122
+ });
123
+ this._onMiddlewareChange.fire({
124
+ trigger: props.trigger,
125
+ method: props.triggerMethod
126
+ });
127
+ const dispose = props.freshTrigger(() => {
128
+ this._onMiddlewareChange.fire({
129
+ trigger: props.trigger,
130
+ method: props.triggerMethod
131
+ });
132
+ });
133
+ this._disposeMap.set(props.id, dispose);
134
+ }
135
+ unUse(id) {
136
+ const target = this._registerById.get(id);
137
+ if (!target) {
138
+ return;
139
+ }
140
+ target.triggerMethod.forEach((item) => {
141
+ const caller = this._getCaller({ trigger: target.trigger, method: item });
142
+ if (!this._registerByCaller.has(caller)) {
143
+ return;
144
+ }
145
+ const triggers = this._registerByCaller.get(caller);
146
+ this._registerByCaller.set(
147
+ caller,
148
+ triggers.filter((_item) => _item === target.id)
149
+ );
150
+ });
151
+ this._onMiddlewareChange.fire({
152
+ trigger: target.trigger,
153
+ method: target.triggerMethod
154
+ });
155
+ const dispose = this._disposeMap.get(id);
156
+ dispose?.dispose();
157
+ this._disposeMap.delete(id);
158
+ }
159
+ _getCaller({ trigger, method }) {
160
+ return `${trigger}-${method.toString()}`;
161
+ }
162
+ };
163
+
164
+ // src/base/base-ui-configuration-service.tsx
165
+ var BaseUiConfigurationService = class extends Disposable {
166
+ constructor(_setting, _containerService) {
167
+ super();
168
+ this._setting = _setting;
169
+ this._containerService = _containerService;
170
+ }
171
+ get setting() {
172
+ return this._setting;
173
+ }
174
+ registerConfig(config) {
175
+ for (const key of Object.keys(config)) {
176
+ this.uiManager[key].registerConfig(config[key]);
177
+ }
178
+ }
179
+ useMiddleware(props) {
180
+ return this.middleware.use(props);
181
+ }
182
+ _bootstrap() {
183
+ this.middleware = this._containerService.createInstance(MiddlewareManager);
184
+ this._initAllManager();
185
+ }
186
+ };
187
+ BaseUiConfigurationService = __decorateClass([
188
+ __decorateParam(1, IContainerService)
189
+ ], BaseUiConfigurationService);
190
+ var BaseSetting = class {
191
+ constructor(options) {
192
+ const defaultConfig = {
193
+ namespace: "base",
194
+ visible: true,
195
+ debugMode: false
196
+ };
197
+ this.observableData = proxy(merge(defaultConfig, options.setting));
198
+ }
199
+ get namespace() {
200
+ return this.observableData.namespace;
201
+ }
202
+ get debugMode() {
203
+ return this.observableData.debugMode;
204
+ }
205
+ get visible() {
206
+ return this.observableData.visible;
207
+ }
208
+ };
209
+ var GlobalContext = createContext();
210
+ var BaseUiManager = class {
211
+ // feat: 修复旧框架跳转新框架闪动
212
+ constructor(_middlewareManager) {
213
+ this._middlewareManager = _middlewareManager;
214
+ this._listenerMiddlewareChange();
215
+ }
216
+ unRegisterConfig(id) {
217
+ lvAssertNotHere(
218
+ "There is no such scenario yet, and no support capability is provided for the time being. If necessary, please contact infrastructure support"
219
+ );
220
+ }
221
+ _listenerMiddlewareChange() {
222
+ this._middlewareManager.onMiddlewareChange((props) => {
223
+ this._middlewareChange(props);
224
+ });
225
+ }
226
+ };
227
+
228
+ // src/utils/sort.ts
229
+ var OrderLevel = /* @__PURE__ */ ((OrderLevel2) => {
230
+ OrderLevel2["high"] = "high";
231
+ OrderLevel2["default"] = "default";
232
+ OrderLevel2["low"] = "low";
233
+ return OrderLevel2;
234
+ })(OrderLevel || {});
235
+ function sortListBySettings({
236
+ list,
237
+ filter = (item) => item
238
+ }) {
239
+ return list.sort((a, b) => {
240
+ const typeSort = { high: 2, default: 1, low: 0 };
241
+ const { orderLevel: aType = "default", order: aPriority = 0 } = a;
242
+ const { orderLevel: bType = "default", order: bPriority = 0 } = b;
243
+ if (aType !== bType) {
244
+ return typeSort[bType] - typeSort[aType];
245
+ }
246
+ return bPriority - aPriority;
247
+ }).map(filter);
248
+ }
249
+
250
+ // src/utils/merged-array.ts
251
+ var mergeUiConfigs = (configs) => {
252
+ const uiConfigs = {};
253
+ configs.map((configObj) => {
254
+ for (const [key, config] of Object.entries(configObj)) {
255
+ if (!Array.isArray(config)) {
256
+ continue;
257
+ }
258
+ if (key in uiConfigs) {
259
+ uiConfigs[key]?.push(...config);
260
+ } else {
261
+ Object.assign(uiConfigs, {
262
+ [key]: config
263
+ });
264
+ }
265
+ }
266
+ });
267
+ return uiConfigs;
268
+ };
269
+
270
+ // src/utils/runner-builder.ts
271
+ function runnerBuilder({
272
+ middleware,
273
+ trigger,
274
+ method,
275
+ handler,
276
+ uiConfig
277
+ }) {
278
+ const runner = middleware.buildRunner({
279
+ trigger,
280
+ method,
281
+ handler,
282
+ uiConfig
283
+ });
284
+ return runner;
285
+ }
286
+
287
+ // src/utils/evaluate.ts
288
+ function evaluate(config, defaultValue, ...args) {
289
+ if (typeof config === "function") {
290
+ return config(...args) ?? defaultValue;
291
+ }
292
+ return config ?? defaultValue;
293
+ }
294
+ var PageRouteManagerSymbol = "PageRoute";
295
+ var KeepAliveStatus = /* @__PURE__ */ ((KeepAliveStatus2) => {
296
+ KeepAliveStatus2["Activated"] = "Activated";
297
+ KeepAliveStatus2["InActivated"] = "InActivated";
298
+ return KeepAliveStatus2;
299
+ })(KeepAliveStatus || {});
300
+ var InitAwaitLock = class {
301
+ constructor() {
302
+ this._mutex = new SharedMutex();
303
+ void this._mutex.lock();
304
+ }
305
+ /**
306
+ * @description 是否已经完成初始化
307
+ */
308
+ get hasBeenDone() {
309
+ return !this._mutex.isLocked();
310
+ }
311
+ /**
312
+ * @description 标记初始化完成并放行
313
+ */
314
+ initDone() {
315
+ if (this.hasBeenDone) {
316
+ return;
317
+ }
318
+ this._mutex.unLock();
319
+ }
320
+ };
321
+
322
+ // src/utils/is-equal.ts
323
+ var isEqualStr = (val, otherVal) => val === otherVal;
324
+ var queryStringify = (parseObj) => {
325
+ if (typeof parseObj !== "object") {
326
+ lvAssertNever(parseObj);
327
+ }
328
+ return Object.entries(parseObj).map((item) => `${item[0]}=${item[1]}`).join("&");
329
+ };
330
+ var ErrorBoundary = ({ children, fallback, onError }) => {
331
+ return /* @__PURE__ */ React.createElement(ErrorBoundary$1, { fallback: fallback ?? /* @__PURE__ */ React.createElement("div", null), onError }, children);
332
+ };
333
+ function useObserverSelector(selectionTarget, selector, options = {}) {
334
+ const { deps } = options;
335
+ if (!selectionTarget) {
336
+ return void 0;
337
+ }
338
+ const snapshot2 = useSnapshot(selectionTarget);
339
+ const selectedValue = useMemo(() => {
340
+ return selector(snapshot2);
341
+ }, [snapshot2, ...deps ?? []]);
342
+ return selectedValue;
343
+ }
344
+
345
+ // src/feature/page-route/component/page-route.module.scss
346
+ var page_route_module_default = {};
347
+
348
+ // src/feature/page-route/component/page-route.tsx
349
+ var PageRoute = ({ layout }) => {
350
+ const navigate2 = useNavigate();
351
+ const { uiConfigurationService } = useContext(GlobalContext);
352
+ const baseRoute = useObserverSelector(uiConfigurationService.setting, (manager) => {
353
+ return {
354
+ namespace: manager.namespace,
355
+ baseRoute: manager.baseRoute,
356
+ redirectRouteIdWhen404: manager.redirectRouteIdWhen404
357
+ };
358
+ });
359
+ const routeConfig = useObserverSelector(
360
+ uiConfigurationService.uiManager[PageRouteManagerSymbol],
361
+ (manager) => {
362
+ return manager.observableData.configs;
363
+ }
364
+ );
365
+ const redirectRouteId = useObserverSelector(uiConfigurationService.setting, (setting) => {
366
+ return setting?.observableData?.redirectRouteIdWhen404;
367
+ });
368
+ const redirectRoute = useMemo(() => {
369
+ if (!redirectRouteId) return void 0;
370
+ return routeConfig.find(({ id }) => id === redirectRouteId);
371
+ }, [redirectRouteId, routeConfig]);
372
+ useEffect(() => {
373
+ const routeManager = uiConfigurationService.uiManager[PageRouteManagerSymbol];
374
+ const { pendingNavigateOptions } = routeManager;
375
+ if (pendingNavigateOptions) {
376
+ navigate2(pendingNavigateOptions.path, pendingNavigateOptions.options);
377
+ }
378
+ const dispose = routeManager.onWouldRouteChange((to, options) => {
379
+ if (typeof to === "string") {
380
+ navigate2(to, options);
381
+ } else {
382
+ navigate2(to);
383
+ }
384
+ });
385
+ routeManager.initDone();
386
+ return () => {
387
+ dispose.dispose();
388
+ };
389
+ }, []);
390
+ const config = useMemo(
391
+ () => routeConfig.map((item) => /* @__PURE__ */ React.createElement(
392
+ Route,
393
+ {
394
+ key: `${item.id}-${item._updateTime}`,
395
+ path: item.path,
396
+ index: item.index,
397
+ element: /* @__PURE__ */ React.createElement(ErrorBoundary, { fallback: item.errorElement ?? /* @__PURE__ */ React.createElement("div", null) }, item.content ? item.content() : item.skeleton?.() ?? null)
398
+ }
399
+ )),
400
+ [routeConfig]
401
+ );
402
+ return /* @__PURE__ */ React.createElement("div", { id: baseRoute.namespace, className: page_route_module_default.root }, /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { element: layout }, config), redirectRoute ? /* @__PURE__ */ React.createElement(Route, { path: "*", element: /* @__PURE__ */ React.createElement(Navigate, { to: redirectRoute.path, replace: true }) }) : null));
403
+ };
404
+ var Repeater = memo((props) => {
405
+ const { mode, children } = props;
406
+ const resolveRef = useRef();
407
+ if (mode === "hidden") {
408
+ startTransition(() => {
409
+ throw new Promise((resolve) => resolveRef.current = resolve);
410
+ });
411
+ }
412
+ if (resolveRef.current) {
413
+ startTransition(() => {
414
+ resolveRef.current?.();
415
+ resolveRef.current = void 0;
416
+ });
417
+ }
418
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
419
+ });
420
+
421
+ // src/feature/page-route/component/keep-alive-outlet/components/offscreen/index.tsx
422
+ var Offscreen = memo((props) => {
423
+ const { mode, children, fallback } = props;
424
+ return /* @__PURE__ */ React.createElement(Suspense, { fallback }, /* @__PURE__ */ React.createElement(Repeater, { mode }, children));
425
+ });
426
+ var isNeedCache = (routesConfig, pathName, updateTime) => {
427
+ for (const route of routesConfig) {
428
+ const isMatch = matchPath(route.path, pathName);
429
+ if (isMatch) {
430
+ const needCache = evaluate(route.isNeedCache, false);
431
+ const hasContentRendered = Boolean(evaluate(route.content, null));
432
+ const updated = !updateTime ? true : updateTime === route._updateTime;
433
+ return needCache && hasContentRendered && updated;
434
+ }
435
+ }
436
+ return false;
437
+ };
438
+
439
+ // src/feature/page-route/component/keep-alive-outlet/utils/outlets.ts
440
+ var getValidOutlets = (routesConfig, pathname, outlets) => {
441
+ outlets.forEach((outletData) => {
442
+ const needRefresh = !(outletData.isCacheItem && isNeedCache(routesConfig, outletData.pathname, outletData?.updateTime));
443
+ if (needRefresh) {
444
+ outletData.outlet = null;
445
+ }
446
+ });
447
+ const newOutlets = outlets.filter((item) => item.outlet);
448
+ return newOutlets;
449
+ };
450
+
451
+ // src/feature/page-route/component/keep-alive-outlet/index.tsx
452
+ var OutletWrapper = ({ visible, updateTime, path, children }) => {
453
+ const { uiConfigurationService } = useContext(GlobalContext);
454
+ useEffect(() => {
455
+ uiConfigurationService.uiManager[PageRouteManagerSymbol].notifyPageRendered(path);
456
+ }, [path, visible, updateTime]);
457
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
458
+ };
459
+ function KeepAliveOutlet({ fallback, routesConfig }) {
460
+ const { uiConfigurationService } = useContext(GlobalContext);
461
+ const location = useLocation();
462
+ const outlet = useOutlet();
463
+ const initRef = useRef(true);
464
+ const handleNotifyActivateRoute = (pathName) => {
465
+ uiConfigurationService.uiManager[PageRouteManagerSymbol].activateKeepAliveRoute(pathName, location.state);
466
+ };
467
+ const calcOutlets = (tempOutlets) => {
468
+ handleNotifyActivateRoute(location.pathname);
469
+ const validTempOutlets = getValidOutlets(routesConfig, location.pathname, tempOutlets);
470
+ let result = validTempOutlets.find((o) => isEqualStr(o.pathname, location.pathname));
471
+ const isCacheItem = isNeedCache(routesConfig, location.pathname);
472
+ const notUpdated = routesConfig.reduce((bool, _config) => {
473
+ if (!bool) {
474
+ return false;
475
+ }
476
+ if (!_config._updateTime) {
477
+ return true;
478
+ }
479
+ return tempOutlets.find((item) => item.pathname === location.pathname)?.updateTime === _config._updateTime;
480
+ }, true);
481
+ if (result && isCacheItem && notUpdated) {
482
+ return validTempOutlets;
483
+ }
484
+ if (!result) {
485
+ const route = uiConfigurationService.uiManager[PageRouteManagerSymbol].getRouteConfigByPath(
486
+ location.pathname
487
+ );
488
+ result = {
489
+ key: location.key,
490
+ pathname: location.pathname,
491
+ updateTime: route?._updateTime,
492
+ isCacheItem,
493
+ outlet
494
+ };
495
+ validTempOutlets.push(result);
496
+ }
497
+ return validTempOutlets;
498
+ };
499
+ const [outlets, setOutlets] = useState(
500
+ // eslint-disable-next-line no-nested-ternary
501
+ uiConfigurationService.uiManager[PageRouteManagerSymbol].pendingNavigateOptions ? [] : initRef.current ? calcOutlets([]) : []
502
+ );
503
+ initRef.current = false;
504
+ useEffect(() => {
505
+ setOutlets(calcOutlets);
506
+ }, [location.pathname, routesConfig]);
507
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, outlets.map((o) => {
508
+ const visibilityMode = isEqualStr(o.pathname, location.pathname) ? "visible" : "hidden";
509
+ return /* @__PURE__ */ React.createElement(Offscreen, { key: o.key, mode: visibilityMode, fallback: fallback || null }, /* @__PURE__ */ React.createElement(
510
+ OutletWrapper,
511
+ {
512
+ updateTime: o.updateTime,
513
+ path: location.pathname,
514
+ visible: visibilityMode === "visible"
515
+ },
516
+ o.outlet
517
+ ));
518
+ }));
519
+ }
520
+ var OutletWrapper2 = ({ visible, updateTime, path, children }) => {
521
+ const { uiConfigurationService } = useContext(GlobalContext);
522
+ useEffect(() => {
523
+ uiConfigurationService.uiManager[PageRouteManagerSymbol].notifyPageRendered(path);
524
+ }, [path, visible, updateTime]);
525
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
526
+ };
527
+ function KeepAliveSingleOutlet({ fallback, routesConfig }) {
528
+ const { uiConfigurationService } = useContext(GlobalContext);
529
+ const location = useLocation();
530
+ const outlet = useOutlet();
531
+ const handleNotifyActivateRoute = (pathName) => {
532
+ uiConfigurationService.uiManager[PageRouteManagerSymbol].activateKeepAliveRoute(pathName, location.state);
533
+ };
534
+ const calcOutlets = useMemoizedFn((tempOutlets) => {
535
+ handleNotifyActivateRoute(location.pathname);
536
+ const validTempOutlets = getValidOutlets(routesConfig, location.pathname, tempOutlets);
537
+ let result = validTempOutlets.find((o) => isEqualStr(o.pathname, location.pathname));
538
+ const isCacheItem = isNeedCache(routesConfig, location.pathname);
539
+ const notUpdated = routesConfig.reduce((bool, _config) => {
540
+ if (!bool) {
541
+ return false;
542
+ }
543
+ if (!_config._updateTime) {
544
+ return true;
545
+ }
546
+ return tempOutlets.find((item) => item.pathname === location.pathname)?.updateTime === _config._updateTime;
547
+ }, true);
548
+ if (result && isCacheItem && notUpdated) {
549
+ return validTempOutlets;
550
+ }
551
+ if (!result) {
552
+ const route = uiConfigurationService.uiManager[PageRouteManagerSymbol].getRouteConfigByPath(
553
+ location.pathname
554
+ );
555
+ result = {
556
+ key: location.key,
557
+ pathname: location.pathname,
558
+ updateTime: route?._updateTime,
559
+ isCacheItem,
560
+ outlet
561
+ };
562
+ validTempOutlets.push(result);
563
+ }
564
+ return validTempOutlets;
565
+ });
566
+ const outlets = useMemo(() => {
567
+ if (uiConfigurationService.uiManager[PageRouteManagerSymbol].pendingNavigateOptions) {
568
+ return [];
569
+ }
570
+ return calcOutlets([]);
571
+ }, [
572
+ uiConfigurationService.uiManager[PageRouteManagerSymbol].pendingNavigateOptions,
573
+ location.pathname,
574
+ routesConfig,
575
+ calcOutlets
576
+ ]);
577
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, outlets.map((o) => {
578
+ const visibilityMode = isEqualStr(o.pathname, location.pathname) ? "visible" : "hidden";
579
+ return /* @__PURE__ */ React.createElement(Offscreen, { key: o.key, mode: visibilityMode, fallback: fallback || null }, /* @__PURE__ */ React.createElement(
580
+ OutletWrapper2,
581
+ {
582
+ updateTime: o.updateTime,
583
+ path: location.pathname,
584
+ visible: visibilityMode === "visible"
585
+ },
586
+ o.outlet
587
+ ));
588
+ }));
589
+ }
590
+
591
+ // src/feature/page-route/page-route-manager.tsx
592
+ var PageRouteManager = class extends BaseUiManager {
593
+ constructor() {
594
+ super(...arguments);
595
+ this.observableData = proxy({
596
+ currentRoute: void 0,
597
+ configs: [],
598
+ keepAliveStatusMap: {},
599
+ historyRoutes: [],
600
+ containerWidth: 0
601
+ });
602
+ this._locker = new InitAwaitLock();
603
+ this._onWouldRouteChange = new Emitter();
604
+ this.onWouldRouteChange = this._onWouldRouteChange.event;
605
+ this._onKeepAliveChange = new Emitter();
606
+ this.onKeepAliveChange = this._onKeepAliveChange.event;
607
+ this._onPageRendered = new Emitter();
608
+ this.onPageRendered = this._onPageRendered.event;
609
+ this._onPageContainerWidthChange = new Emitter();
610
+ this.onPageContainerWidthChange = this._onPageContainerWidthChange.event;
611
+ // fix: 修复个人页刷新打开埋点参数上报错误
612
+ this._onRouteConfigChange = new Emitter();
613
+ this.onRouteConfigChange = this._onRouteConfigChange.event;
614
+ }
615
+ get pendingNavigateOptions() {
616
+ return this._pendingNavigateOptions;
617
+ }
618
+ get currentRoute() {
619
+ return this.getRouteConfigByPath(this.observableData.currentRoute);
620
+ }
621
+ registerConfig(configs) {
622
+ configs.forEach((config) => {
623
+ const idx = this.observableData.configs.findIndex((item) => item.id === config.id);
624
+ if (idx !== -1) {
625
+ this.observableData.configs[idx] = merge(this.observableData.configs[idx], config, {
626
+ _updateTime: Date.now()
627
+ });
628
+ } else {
629
+ this.observableData.configs.push(
630
+ merge({}, config, {
631
+ _updateTime: 0
632
+ })
633
+ );
634
+ }
635
+ });
636
+ this._onRouteConfigChange.fire(snapshot(this.observableData.configs));
637
+ }
638
+ updatePageRoute(path) {
639
+ const routesLength = this.observableData.historyRoutes.length;
640
+ if (this.observableData.historyRoutes[routesLength - 1] !== path) {
641
+ this.observableData.historyRoutes.push(path);
642
+ }
643
+ const preRoute = this.getRouteConfigByPath(this.observableData.currentRoute);
644
+ const setRoute = this.getRouteConfigByPath(path);
645
+ if (preRoute?.id !== setRoute?.id) {
646
+ if (preRoute) {
647
+ preRoute?.onActiveChange?.({ active: false });
648
+ }
649
+ setRoute?.onActiveChange?.({ active: true });
650
+ }
651
+ this.observableData.currentRoute = path;
652
+ }
653
+ navigate(id, options) {
654
+ const path = this.generatePath(id, options);
655
+ if (!path) {
656
+ lvAssert(path);
657
+ }
658
+ const runner = runnerBuilder({
659
+ middleware: this._middlewareManager,
660
+ trigger: PageRouteManagerSymbol,
661
+ method: "shouldInterceptNavigate",
662
+ uiConfig: { id, path }
663
+ });
664
+ const interceptRes = runner.run();
665
+ if (runner.isStop || interceptRes) {
666
+ return;
667
+ }
668
+ this._navigateByPath(path, options);
669
+ }
670
+ _navigateByPath(path, options) {
671
+ if (!this._locker.hasBeenDone) {
672
+ this._pendingNavigateOptions = {
673
+ path,
674
+ options
675
+ };
676
+ } else {
677
+ this._onWouldRouteChange.fire(path, options);
678
+ }
679
+ }
680
+ updateContainerWidth(width) {
681
+ this.observableData.containerWidth = width;
682
+ }
683
+ initDone() {
684
+ if (this._locker.hasBeenDone) {
685
+ return;
686
+ }
687
+ this._pendingNavigateOptions = void 0;
688
+ this._locker.initDone();
689
+ }
690
+ navigateBack(to = -1) {
691
+ this._onWouldRouteChange.fire(to);
692
+ }
693
+ generatePath(id, options) {
694
+ const target = this.observableData.configs.find((item) => item.id === id);
695
+ if (!target) {
696
+ lvAssert(target);
697
+ }
698
+ const compiler = compile(target.path);
699
+ let result = compiler(options?.params ?? {});
700
+ const query = typeof options?.query === "string" ? options.query : queryStringify(options?.query ?? {});
701
+ if (query.length !== 0) {
702
+ result += query.includes("?") ? query : `?${query}`;
703
+ }
704
+ return result;
705
+ }
706
+ activateKeepAliveRoute(activatePathName, locationState) {
707
+ if (activatePathName === this.currentKeepAliveData?.pathName && Object.values(this.observableData.keepAliveStatusMap).length > 0) {
708
+ return;
709
+ }
710
+ const allAlivePathName = Object.keys(this.observableData.keepAliveStatusMap);
711
+ for (const alivePathName of allAlivePathName) {
712
+ if (isEqualStr(alivePathName, activatePathName)) {
713
+ continue;
714
+ }
715
+ this._updateKeepAliveStatus(alivePathName, "InActivated" /* InActivated */);
716
+ }
717
+ this._updateKeepAliveStatus(activatePathName, "Activated" /* Activated */, locationState);
718
+ }
719
+ _updateKeepAliveStatus(pathName, status, locationState) {
720
+ const lastStatusVal = this.observableData.keepAliveStatusMap[pathName];
721
+ const lastStatus = lastStatusVal?.status;
722
+ const matchRoteConfig = this.observableData.configs.find((item) => matchPath(item.path, pathName));
723
+ const newStatusVal = {
724
+ pathName,
725
+ status,
726
+ routeId: matchRoteConfig?.id ?? "NOT_FOUND",
727
+ locationState
728
+ };
729
+ this.observableData.keepAliveStatusMap[pathName] = newStatusVal;
730
+ if (status !== lastStatus) {
731
+ this._onKeepAliveChange.fire(newStatusVal);
732
+ }
733
+ }
734
+ get currentKeepAliveData() {
735
+ const { keepAliveStatusMap, currentRoute = "" } = this.observableData;
736
+ return Object.values(keepAliveStatusMap).find((item) => item.status === "Activated" /* Activated */);
737
+ }
738
+ notifyPageRendered(config) {
739
+ if (typeof config === "string") {
740
+ const routeConfig = this.getRouteConfigByPath(config);
741
+ this._onPageRendered.fire(routeConfig ? snapshot(routeConfig) : routeConfig);
742
+ } else {
743
+ this._onPageRendered.fire(config);
744
+ }
745
+ }
746
+ getRouteConfigByPath(path) {
747
+ if (!path) {
748
+ return void 0;
749
+ }
750
+ return this.observableData.configs.find((item) => matchPath(item.path, path));
751
+ }
752
+ render(options) {
753
+ return /* @__PURE__ */ React.createElement(PageRoute, { layout: options.layout });
754
+ }
755
+ renderOutlet(options) {
756
+ return /* @__PURE__ */ React.createElement(KeepAliveOutlet, { ...options });
757
+ }
758
+ renderSingleOutlet(options) {
759
+ return /* @__PURE__ */ React.createElement(KeepAliveSingleOutlet, { ...options });
760
+ }
761
+ _middlewareChange(props) {
762
+ }
763
+ };
764
+ var useKeepAliveEffect = (cb) => {
765
+ const { uiConfigurationService } = useContext(GlobalContext);
766
+ const location = useLocation();
767
+ const initedLocationPathName = useRef(location.pathname);
768
+ const disposeCb = useRef(null);
769
+ const handleTrggerEffect = (data) => {
770
+ if (!data) {
771
+ return;
772
+ }
773
+ if (data.pathName !== initedLocationPathName.current) {
774
+ return;
775
+ }
776
+ if (data.status === "Activated" /* Activated */) {
777
+ disposeCb.current = cb?.();
778
+ } else {
779
+ disposeCb.current?.();
780
+ }
781
+ };
782
+ useEffect(() => {
783
+ const pageRouteManager = uiConfigurationService.uiManager[PageRouteManagerSymbol];
784
+ handleTrggerEffect(pageRouteManager.currentKeepAliveData);
785
+ const diposeEvent = pageRouteManager.onKeepAliveChange((data) => {
786
+ handleTrggerEffect(data);
787
+ });
788
+ return () => {
789
+ diposeEvent.dispose();
790
+ disposeCb.current?.();
791
+ };
792
+ }, []);
793
+ };
794
+ var useKeepAliveLayoutEffect = (cb) => {
795
+ const { uiConfigurationService } = useContext(GlobalContext);
796
+ const location = useLocation();
797
+ const initedLocationPathName = useRef(location.pathname);
798
+ const disposeCb = useRef(null);
799
+ const handleTrggerEffect = (data) => {
800
+ if (!data) {
801
+ return;
802
+ }
803
+ if (data.pathName !== initedLocationPathName.current) {
804
+ return;
805
+ }
806
+ if (data.status === "Activated" /* Activated */) {
807
+ disposeCb.current = cb?.();
808
+ } else {
809
+ disposeCb.current?.();
810
+ }
811
+ };
812
+ useLayoutEffect(() => {
813
+ const pageRouteManager = uiConfigurationService.uiManager[PageRouteManagerSymbol];
814
+ handleTrggerEffect(pageRouteManager.currentKeepAliveData);
815
+ const diposeEvent = pageRouteManager.onKeepAliveChange((data) => {
816
+ handleTrggerEffect(data);
817
+ });
818
+ return () => {
819
+ diposeEvent.dispose();
820
+ disposeCb.current?.();
821
+ };
822
+ }, []);
823
+ };
824
+ var usePageContainerWidth = () => {
825
+ const { uiConfigurationService } = useContext(GlobalContext);
826
+ return useObserverSelector(uiConfigurationService.uiManager[PageRouteManagerSymbol], (manager) => {
827
+ return manager.observableData.containerWidth;
828
+ });
829
+ };
830
+ function navigate(platformUiConfiguration, to, options) {
831
+ const pageRouteManager = platformUiConfiguration.uiManager[PageRouteManagerSymbol];
832
+ switch (true) {
833
+ case (typeof to === "string" || typeof to === "object"):
834
+ if (typeof to === "object") {
835
+ to = createPath(to);
836
+ }
837
+ const path = parsePath(to);
838
+ const routesConfig = pageRouteManager.observableData.configs;
839
+ const matchItem = routesConfig.find((item) => matchPath(item.path, path?.pathname ?? ""));
840
+ if (!matchItem) {
841
+ return;
842
+ }
843
+ const matchRes = Object.entries(matchPath(matchItem.path, path?.pathname ?? "")?.params ?? {}).reduce((pre, cur) => {
844
+ const [key, value] = cur;
845
+ if (!key || !value) {
846
+ return pre;
847
+ }
848
+ pre[key] = value;
849
+ return pre;
850
+ }, {});
851
+ pageRouteManager.navigate(matchItem.id, {
852
+ query: path.search,
853
+ params: matchRes,
854
+ ...options
855
+ });
856
+ break;
857
+ case typeof to === "number":
858
+ pageRouteManager.navigateBack(to);
859
+ break;
860
+ }
861
+ }
862
+ var useNavigateFactory = (uiConfigurationService) => {
863
+ const useNavigate2 = useMemoizedFn((to, options) => {
864
+ navigate(uiConfigurationService, to, options);
865
+ });
866
+ return useNavigate2;
867
+ };
868
+
869
+ // src/feature/block-content/block-content-manager.interface.ts
870
+ var BlockContentManagerSymbol = "BlockContent";
871
+
872
+ // src/feature/block-content/component/block-content.module.scss
873
+ var block_content_module_default = {};
874
+
875
+ // src/feature/block-content/component/block-content.tsx
876
+ var BlockContentComponent = React3.memo(() => {
877
+ const { uiConfigurationService } = useContext(GlobalContext);
878
+ const activeBlockContentConfig = useObserverSelector(
879
+ uiConfigurationService.uiManager[BlockContentManagerSymbol],
880
+ (manager) => {
881
+ const { activeId, configs } = manager.observableData;
882
+ return configs.find((item) => item.id === activeId);
883
+ }
884
+ );
885
+ const containerRef = useRef(null);
886
+ return /* @__PURE__ */ React3.createElement(
887
+ "div",
888
+ {
889
+ ref: containerRef,
890
+ className: cs(block_content_module_default.container, evaluate(activeBlockContentConfig?.className, ""))
891
+ },
892
+ evaluate(activeBlockContentConfig?.content, null)
893
+ );
894
+ });
895
+ var BlockContent = BlockContentComponent;
896
+
897
+ // src/feature/block-content/block-content-manager.tsx
898
+ var BlockContentManager = class extends BaseUiManager {
899
+ constructor() {
900
+ super(...arguments);
901
+ this.observableData = proxy({
902
+ forceUpdate: 0,
903
+ activeId: void 0,
904
+ configs: []
905
+ });
906
+ }
907
+ registerConfig(configs) {
908
+ configs.forEach((config) => {
909
+ const idx = this.observableData.configs.findIndex((item) => item.id === config.id);
910
+ if (idx !== -1) {
911
+ this.observableData.configs[idx] = merge(this.observableData.configs[idx], config);
912
+ } else {
913
+ lvAssertNotNil(
914
+ config.id,
915
+ `The "id" attribute is required when registering "UiManagerName.BlockContent"`
916
+ );
917
+ this.observableData.configs.push(config);
918
+ }
919
+ });
920
+ if (!(this.observableData.activeId && this.observableData.configs.find((item) => item.id === this.observableData.activeId))) {
921
+ this.observableData.activeId = this.observableData.configs[0]?.id;
922
+ }
923
+ }
924
+ changeActiveId(activeId) {
925
+ this.observableData.activeId = activeId;
926
+ }
927
+ render() {
928
+ return /* @__PURE__ */ React.createElement(BlockContent, null);
929
+ }
930
+ _middlewareChange() {
931
+ this.observableData.forceUpdate++;
932
+ }
933
+ };
934
+
935
+ export { BaseSetting, BaseUiConfigurationService, BaseUiManager, BlockContentManager, BlockContentManagerSymbol, GlobalContext, KeepAliveStatus, MiddlewareManager, OrderLevel, PageRouteManager, PageRouteManagerSymbol, evaluate, mergeUiConfigs, runnerBuilder, sortListBySettings, useKeepAliveEffect, useKeepAliveLayoutEffect, useNavigateFactory, usePageContainerWidth };
936
+ //# sourceMappingURL=index.js.map
937
+ //# sourceMappingURL=index.js.map