@bbki.ng/site 5.8.2 → 5.8.4

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 (30) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +2 -2
  3. package/src/app/app.tsx +4 -8
  4. package/src/app/components/BaseLayout.tsx +2 -3
  5. package/src/app/components/cover/index.tsx +17 -15
  6. package/src/app/hooks/use_plugin_entries.ts +17 -27
  7. package/src/core/components/SlotComp.tsx +4 -17
  8. package/src/core/hooks/index.ts +2 -2
  9. package/src/core/hooks/useMiddlewareTransData.ts +13 -82
  10. package/src/core/hooks/useSlotComp.ts +3 -26
  11. package/src/core/hooks/use_plugins.ts +4 -3
  12. package/src/core/plugin-system/pluginManager.ts +5 -2
  13. package/src/core/plugin-system/pluginManifestService.ts +2 -18
  14. package/src/core/plugin-system/pluginStore.ts +1 -0
  15. package/src/core/plugin-system/registry.ts +1 -106
  16. package/src/core/plugin-system/services/systemUIService.ts +31 -126
  17. package/src/core/shared-service/contract/IUIService.ts +15 -17
  18. package/src/core/shared-service/factory/createUIService.ts +121 -0
  19. package/src/core/shared-service/factory/createUIServiceReactKit.tsx +149 -0
  20. package/src/plugins/blog/components/BlogSlotCom.tsx +4 -17
  21. package/src/plugins/blog/hooks/useMiddlewareTransData.ts +11 -76
  22. package/src/plugins/blog/hooks/use_blog_slot_com.ts +2 -24
  23. package/src/plugins/blog/index.ts +6 -1
  24. package/src/plugins/blog/services/BlogUIService.ts +10 -103
  25. package/src/plugins/blog/services/IBlogUIService.ts +1 -16
  26. package/src/plugins/store/components/storeIcon.tsx +16 -0
  27. package/src/plugins/store/index.ts +3 -1
  28. package/src/types/slots.ts +0 -17
  29. package/tsconfig.json +1 -1
  30. package/src/utils/index.tsx +0 -20
@@ -1,26 +1,14 @@
1
- import type React from 'react';
2
-
3
- import { IMiddlewareEntry, ISlotEntry } from '#/core/plugin-system/registry';
4
- import { createEventBus } from '#/core/utils/eventBus';
5
- import { IComPropsRegisteredToSlot } from '#/types/slots';
1
+ import { createUIService } from '#/core/shared-service/factory/createUIService';
6
2
 
7
3
  import { BlogDataHookPoint, BlogSlotName, IBlogUIService } from './IBlogUIService';
8
4
 
9
- type RegistryEvents = {
10
- 'blog:slots:changed': void;
11
- 'blog:middleware:changed': BlogDataHookPoint;
12
- };
5
+ const baseService = createUIService<BlogSlotName, BlogDataHookPoint>('blog');
13
6
 
14
7
  export class BlogUIService implements IBlogUIService {
15
8
  private static instance: BlogUIService;
16
9
 
17
10
  private constructor() {}
18
11
 
19
- private slots = new Map<BlogSlotName, Array<ISlotEntry>>();
20
- private middlewares = new Map<BlogDataHookPoint, IMiddlewareEntry<unknown>[]>();
21
-
22
- private bus = createEventBus<RegistryEvents>();
23
-
24
12
  static getInstance(): BlogUIService {
25
13
  if (!BlogUIService.instance) {
26
14
  BlogUIService.instance = new BlogUIService();
@@ -28,93 +16,12 @@ export class BlogUIService implements IBlogUIService {
28
16
  return BlogUIService.instance;
29
17
  }
30
18
 
31
- subscribeSlotChange(listener: () => void) {
32
- return this.bus.on('blog:slots:changed', listener);
33
- }
34
-
35
- subscribeMiddlewareChange(listener: (hookPoint: BlogDataHookPoint) => void) {
36
- return this.bus.on('blog:middleware:changed', listener);
37
- }
38
-
39
- registerMiddleware: <S>(
40
- hookPoint: BlogDataHookPoint,
41
- fn: (data: S) => S | Promise<S>,
42
- pluginId: string,
43
- weight?: number
44
- ) => void = <S>(
45
- hookPoint: BlogDataHookPoint,
46
- fn: (data: S) => S | Promise<S>,
47
- pluginId: string,
48
- weight = 0
49
- ) => {
50
- const existing = this.middlewares.get(hookPoint) || [];
51
-
52
- const newEntry: IMiddlewareEntry<S> = {
53
- id: `${pluginId}-${hookPoint}-middleware`,
54
- pluginId,
55
- fn,
56
- weight,
57
- };
58
-
59
- const updated = [...existing, newEntry as IMiddlewareEntry<unknown>].sort(
60
- (a, b) => (b.weight || 0) - (a.weight || 0)
61
- );
62
- this.middlewares.set(hookPoint, updated);
63
-
64
- this.bus.emit('blog:middleware:changed', hookPoint);
65
- };
66
-
67
- registerSlot: (
68
- slotName: BlogSlotName,
69
- component: React.ComponentType<{ data: unknown }>,
70
- pluginId: string,
71
- weight?: number
72
- ) => void = (slotName, component, pluginId, weight = 0) => {
73
- const existing = this.slots.get(slotName) || [];
74
- const newEntry: ISlotEntry = {
75
- id: `${pluginId}-${slotName}-slot`,
76
- pluginId,
77
- component,
78
- weight,
79
- };
80
-
81
- const updated = [...existing, newEntry].sort((a, b) => (b.weight || 0) - (a.weight || 0));
82
- this.slots.set(slotName, updated);
83
-
84
- this.bus.emit('blog:slots:changed', undefined);
85
- };
86
-
87
- unregisterAllByPluginId: (pluginId: string) => void = pluginId => {
88
- // 移除中间件
89
- this.middlewares.forEach((entries, hookPoint) => {
90
- const filtered = entries.filter(entry => entry.pluginId !== pluginId);
91
- if (filtered.length !== entries.length) {
92
- this.middlewares.set(hookPoint, filtered);
93
- this.bus.emit('blog:middleware:changed', hookPoint);
94
- }
95
- });
96
-
97
- // 移除插槽组件
98
- this.slots.forEach((entries, slotName) => {
99
- const filtered = entries.filter(entry => entry.pluginId !== pluginId);
100
- if (filtered.length !== entries.length) {
101
- this.slots.set(slotName, filtered);
102
- }
103
- });
104
-
105
- this.bus.emit('blog:slots:changed', undefined);
106
- };
107
-
108
- getComponents(slotName: BlogSlotName): React.ComponentType<IComPropsRegisteredToSlot>[] {
109
- return (this.slots.get(slotName) || []).map(entry => entry.component);
110
- }
111
-
112
- async runMiddlewares<T>(point: BlogDataHookPoint, data: T): Promise<T> {
113
- const fns = (this.middlewares.get(point) || []).map(entry => entry.fn);
114
- let result = data;
115
- for (const fn of fns) {
116
- result = (await fn(result)) as T;
117
- }
118
- return result;
119
- }
19
+ registerSlot = baseService.registerSlot.bind(baseService);
20
+ registerMiddleware = baseService.registerMiddleware.bind(baseService);
21
+ unregisterAllByPluginId = baseService.unregisterAllByPluginId.bind(baseService);
22
+ getSlotEntries = baseService.getSlotEntries.bind(baseService);
23
+ getComponents = baseService.getComponents.bind(baseService);
24
+ subscribeSlotChange = baseService.subscribeSlotChange.bind(baseService);
25
+ subscribeMiddlewareChange = baseService.subscribeMiddlewareChange.bind(baseService);
26
+ runMiddlewares = baseService.runMiddlewares.bind(baseService);
120
27
  }
@@ -1,5 +1,3 @@
1
- import type React from 'react';
2
-
3
1
  import { type IBaseUIService } from '#/core/shared-service/contract/IUIService';
4
2
 
5
3
  declare module '#/core/shared-service/service-registry' {
@@ -15,17 +13,4 @@ export type BlogDataHookPoint =
15
13
  | 'blog:transformPostContent'
16
14
  | 'blog:transformTitleList';
17
15
 
18
- export interface IBlogUIService extends IBaseUIService<BlogSlotName, BlogDataHookPoint> {
19
- registerMiddleware: <S>(
20
- hookPoint: BlogDataHookPoint,
21
- fn: (data: S) => S | Promise<S>,
22
- pluginId: string,
23
- weight?: number
24
- ) => void;
25
- registerSlot: (
26
- slotName: BlogSlotName,
27
- component: React.ComponentType<{ data: unknown }>,
28
- pluginId: string,
29
- weight?: number
30
- ) => void;
31
- }
16
+ export interface IBlogUIService extends IBaseUIService<BlogSlotName, BlogDataHookPoint> {}
@@ -0,0 +1,16 @@
1
+ import { Link } from '@bbki.ng/ui';
2
+
3
+ const CupIcon = () => (
4
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
5
+ <path d="M8.75 8h6.5a.75.75 0 0 1 .75.75v6.5a.75.75 0 0 1-.75.75h-6.5a.75.75 0 0 1-.75-.75v-6.5A.75.75 0 0 1 8.75 8Zm.75 6.5h5v-5h-5Z"></path>
6
+ <path d="M15.25 1a.75.75 0 0 1 .75.75V4h2.25c.966 0 1.75.784 1.75 1.75V8h2.25a.75.75 0 0 1 0 1.5H20v5h2.25a.75.75 0 0 1 0 1.5H20v2.25A1.75 1.75 0 0 1 18.25 20H16v2.25a.75.75 0 0 1-1.5 0V20h-5v2.25a.75.75 0 0 1-1.5 0V20H5.75A1.75 1.75 0 0 1 4 18.25V16H1.75a.75.75 0 0 1 0-1.5H4v-5H1.75a.75.75 0 0 1 0-1.5H4V5.75C4 4.784 4.784 4 5.75 4H8V1.75a.75.75 0 0 1 1.5 0V4h5V1.75a.75.75 0 0 1 .75-.75Zm3 17.5a.25.25 0 0 0 .25-.25V5.75a.25.25 0 0 0-.25-.25H5.75a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25Z"></path>
7
+ </svg>
8
+ );
9
+
10
+ export const StoreIcon = () => {
11
+ return (
12
+ <Link to="/store" className="flex items-center">
13
+ <CupIcon />
14
+ </Link>
15
+ );
16
+ };
@@ -2,6 +2,7 @@ import { BBPlugin } from '#/core/plugin-system/bbplugin';
2
2
  import { IHostContext } from '#/types/hostApi';
3
3
  import { PluginID } from '#/types/plugin';
4
4
 
5
+ import { StoreIcon } from './components/storeIcon';
5
6
  import { StorePage } from './components/storePage';
6
7
  import { StoreCtx } from './context';
7
8
 
@@ -20,10 +21,11 @@ export class StorePlugin extends BBPlugin {
20
21
  return;
21
22
  }
22
23
 
24
+ systemUIService.registerSlot('nav-right', StoreIcon, this.id);
25
+
23
26
  systemUIService.registerPluginEntry(
24
27
  {
25
28
  path: '/store',
26
- label: 'cd ./store',
27
29
  pageComponent: StoreCtx.withCtx(
28
30
  {
29
31
  install: ctx.store?.installPlugin || (async () => false),
@@ -1,20 +1,3 @@
1
- export type SlotName =
2
- | 'leftCol'
3
- | 'rightCol'
4
- | 'articleActionRow'
5
- | 'logo'
6
- | 'route'
7
- | 'pageFooter'
8
- | 'articleTitle';
9
-
10
- export type HookPoint =
11
- | 'filterPosts'
12
- | 'transformPostContent'
13
- | 'transformBreadcrumbPath'
14
- | 'transformTitleList'
15
- | 'extendedRoutes'
16
- | 'transformCoverEntry';
17
-
18
1
  export interface IComPropsRegisteredToSlot {
19
2
  data: unknown;
20
3
  }
package/tsconfig.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "extends": "../../tsconfig.base.json",
3
3
  "compilerOptions": {
4
4
  "lib": ["DOM", "DOM.Iterable", "ESNext"],
5
- "jsx": "react",
5
+ "jsx": "react-jsx",
6
6
  "noEmit": true,
7
7
  "moduleResolution": "bundler",
8
8
  "paths": {
@@ -1,20 +0,0 @@
1
- import { PathRouteProps } from 'react-router-dom';
2
- import React from 'react';
3
-
4
- import { IPluginEntry } from '#/types/plugin';
5
- import { IComPropsRegisteredToSlot } from '#/types/slots';
6
-
7
- export const buildEntrySlotCom = (entry: IPluginEntry) => {
8
- const Component = (props: IComPropsRegisteredToSlot) => {
9
- const route = props.data as Omit<PathRouteProps, 'element'>;
10
- if (route.path === entry.path) {
11
- const Com = entry.pageComponent;
12
- return <Com data={props.data} />;
13
- }
14
- return null;
15
- };
16
-
17
- Component.displayName = `EntrySlotCom(${entry.path})`;
18
-
19
- return Component;
20
- };