@bbki.ng/site 5.5.18 → 5.5.20

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 (43) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/index.d.ts +7 -6
  3. package/package.json +3 -3
  4. package/src/blog/app.tsx +18 -54
  5. package/src/blog/components/BaseLayout.tsx +55 -0
  6. package/src/blog/components/index.tsx +2 -4
  7. package/src/blog/context/global_loading_state_provider.tsx +3 -9
  8. package/src/blog/hooks/use_loading.ts +1 -1
  9. package/src/blog/hooks/use_plugin_entries.ts +48 -0
  10. package/src/blog/hooks/use_posts.ts +16 -9
  11. package/src/blog/index.tsx +1 -0
  12. package/src/blog/pages/cover/index.tsx +33 -24
  13. package/src/blog/pages/extensions/txt/article.tsx +6 -3
  14. package/src/blog/pages/extensions/txt/index.tsx +29 -25
  15. package/src/blog/swr.tsx +3 -2
  16. package/src/blog/types/path.ts +0 -7
  17. package/src/blog/utils/index.ts +0 -21
  18. package/src/core/context/createPluginCtx.tsx +12 -7
  19. package/src/core/hooks/index.ts +1 -1
  20. package/src/core/hooks/useMiddlewareTransData.ts +32 -46
  21. package/src/core/hooks/useSlotComp.ts +7 -3
  22. package/src/core/hooks/use_plugins.ts +16 -5
  23. package/src/core/pluginManager.ts +15 -6
  24. package/src/core/registry.ts +45 -11
  25. package/src/plugins/extra-entry/components/page.tsx +14 -0
  26. package/src/plugins/extra-entry/index.ts +32 -0
  27. package/src/plugins/manifest.ts +6 -0
  28. package/src/plugins/sticker/components/StickerCom.tsx +6 -8
  29. package/src/plugins/xwy/components/logo.tsx +6 -2
  30. package/src/plugins/xwy/const/index.ts +1 -1
  31. package/src/types/hostApi.ts +3 -3
  32. package/src/types/plugin.ts +11 -1
  33. package/src/types/posts.ts +9 -0
  34. package/src/types/slots.ts +12 -2
  35. package/src/utils/index.tsx +52 -0
  36. package/tsconfig.json +2 -4
  37. package/src/blog/components/Auth.tsx +0 -13
  38. package/src/blog/components/DelayFadeIn/DelayFadeIn.tsx +0 -28
  39. package/src/blog/components/Spinner.tsx +0 -10
  40. package/src/blog/components/my_suspense.tsx +0 -11
  41. package/src/blog/components/share/share-btn.tsx +0 -28
  42. package/src/blog/components/share/share-icon.tsx +0 -19
  43. package/src/blog/hooks/use_font_loading.ts +0 -41
@@ -1,5 +1,5 @@
1
1
  export { useSlotComp } from './useSlotComp';
2
- export { useMiddlewareTransData } from './useMiddlewareTransData';
2
+ export { useMiddlewareRunner } from './useMiddlewareTransData';
3
3
  export type {
4
4
  UseMiddlewareTransDataOptions,
5
5
  UseMiddlewareTransDataResult,
@@ -1,68 +1,54 @@
1
- import { useState, useEffect, useCallback, useRef } from 'react';
1
+ import { useState, useEffect, useCallback } from 'react';
2
2
 
3
3
  import { registry } from '#/core/registry';
4
4
  import type { HookPoint } from '#/types/slots';
5
5
 
6
- export interface UseMiddlewareTransDataOptions<T> {
6
+ export interface UseMiddlewareTransDataOptions {
7
7
  hookPoint: HookPoint;
8
- baseData: T;
9
- immediate?: boolean;
8
+ onMiddlewareChange?: () => void; // 通知外部,由外部决定是否 run
10
9
  }
11
10
 
12
11
  export interface UseMiddlewareTransDataResult<T> {
13
- data: T | undefined;
14
12
  loading: boolean;
15
13
  error: Error | null;
16
- run: () => Promise<T>;
14
+ run: (inputData: T) => Promise<T>;
17
15
  }
18
16
 
19
- export function useMiddlewareTransData<T>({
17
+ export function useMiddlewareRunner<T>({
20
18
  hookPoint,
21
- baseData,
22
- immediate = true,
23
- }: UseMiddlewareTransDataOptions<T>): UseMiddlewareTransDataResult<T> {
24
- const [data, setData] = useState<T | undefined>(undefined);
19
+ onMiddlewareChange,
20
+ }: UseMiddlewareTransDataOptions): UseMiddlewareTransDataResult<T> {
25
21
  const [loading, setLoading] = useState(false);
26
22
  const [error, setError] = useState<Error | null>(null);
27
23
 
28
- const immediateRef = useRef(immediate);
29
- immediateRef.current = immediate;
30
-
31
- const run = useCallback(async (): Promise<T> => {
32
- setLoading(true);
33
- setError(null);
34
-
35
- try {
36
- const result = await registry.runMiddleware(hookPoint, baseData);
37
- setData(result);
38
- return result;
39
- } catch (err) {
40
- const error = err instanceof Error ? err : new Error(String(err));
41
- setError(error);
42
- throw error;
43
- } finally {
44
- setLoading(false);
45
- }
46
- }, [hookPoint, baseData]);
47
-
24
+ const run = useCallback(
25
+ async (inputData: T) => {
26
+ setLoading(true);
27
+ setError(null);
28
+ try {
29
+ const result = await registry.runMiddleware(hookPoint, inputData);
30
+ return result;
31
+ } catch (err) {
32
+ const error = err instanceof Error ? err : new Error(String(err));
33
+ setError(error);
34
+ throw error;
35
+ } finally {
36
+ setLoading(false);
37
+ }
38
+ },
39
+ [hookPoint]
40
+ );
41
+
42
+ // 仅通知,不执行
48
43
  useEffect(() => {
49
- if (!immediateRef.current) return;
50
-
51
- let cancelled = false;
52
-
53
- run()
54
- .then(result => {
55
- if (cancelled) return;
56
- setData(result);
57
- })
58
- .catch(() => {
59
- // 错误已在 run 中设置到 state
60
- });
44
+ const unsubscribe = registry.subscribeMiddleware(hookPoint, () => {
45
+ onMiddlewareChange?.();
46
+ });
61
47
 
62
48
  return () => {
63
- cancelled = true;
49
+ unsubscribe();
64
50
  };
65
- }, [hookPoint, baseData, run]);
51
+ }, [hookPoint, onMiddlewareChange]);
66
52
 
67
- return { data, loading, error, run };
53
+ return { loading, error, run };
68
54
  }
@@ -1,13 +1,17 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
 
3
- import { SlotName } from '#/types/slots';
3
+ import { IComPropsRegisteredToSlot, SlotName } from '#/types/slots';
4
4
 
5
5
  import { registry } from '../registry';
6
6
 
7
7
  export const useSlotComp = (slotName: SlotName) => {
8
- const [components, setComponents] = useState<React.ComponentType<any>[]>([]);
8
+ const [components, setComponents] = useState<React.ComponentType<IComPropsRegisteredToSlot>[]>(
9
+ () => registry.getComponents(slotName)
10
+ );
9
11
 
10
12
  useEffect(() => {
13
+ setComponents(registry.getComponents(slotName));
14
+
11
15
  const unsubscribe = registry.subscribe(() => {
12
16
  const comps = registry.getComponents(slotName);
13
17
  setComponents(comps);
@@ -16,7 +20,7 @@ export const useSlotComp = (slotName: SlotName) => {
16
20
  return () => {
17
21
  unsubscribe();
18
22
  };
19
- }, []);
23
+ }, [slotName]);
20
24
 
21
25
  return components;
22
26
  };
@@ -1,4 +1,4 @@
1
- import { useEffect } from 'react';
1
+ import { useCallback, useEffect, useState } from 'react';
2
2
 
3
3
  import { pluginManager } from '#/core/pluginManager';
4
4
  import { PluginID } from '#/types/plugin';
@@ -13,11 +13,20 @@ import { PluginID } from '#/types/plugin';
13
13
  * usePlugins(['sticker', 'fontstyler']);
14
14
  */
15
15
  export const usePlugins = (pluginIds: Array<PluginID>) => {
16
+ const [done, setDone] = useState(false);
17
+
18
+ const loadAllPlugins = useCallback(async () => {
19
+ try {
20
+ await Promise.all(pluginIds.map(id => pluginManager.loadPlugin(id)));
21
+ setDone(true);
22
+ } catch (error) {
23
+ console.error('Error loading plugins:', error);
24
+ }
25
+ }, [pluginIds]);
26
+
16
27
  useEffect(() => {
17
28
  // 加载指定的插件
18
- pluginIds.forEach(id => {
19
- pluginManager.loadPlugin(id);
20
- });
29
+ loadAllPlugins();
21
30
 
22
31
  return () => {
23
32
  // 卸载所有指定的插件
@@ -25,5 +34,7 @@ export const usePlugins = (pluginIds: Array<PluginID>) => {
25
34
  pluginManager.disablePlugin(id);
26
35
  });
27
36
  };
28
- }, [pluginIds]);
37
+ }, [loadAllPlugins, pluginIds]);
38
+
39
+ return done;
29
40
  };
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
2
 
3
3
  import { IHostContext } from '#/types/hostApi';
4
- import { registry } from './registry';
5
- import type { SlotName, HookPoint } from '#/types/slots';
4
+ import type { SlotName, HookPoint, IComPropsRegisteredToSlot } from '#/types/slots';
6
5
  import { IPlugin } from '#/types/plugin';
7
6
  import { getStableDeviceId } from '@/utils/fingerprints';
7
+
8
+ import { registry } from './registry';
9
+
8
10
  const pluginModules = import.meta.glob('../plugins/*/index.ts');
9
11
 
10
12
  class PluginManager {
@@ -13,13 +15,18 @@ class PluginManager {
13
15
  private createHostContext(): IHostContext {
14
16
  return {
15
17
  api: {
16
- registerMiddleware: (point: HookPoint, fn: Function, pluginId: string, weight = 0) => {
18
+ registerMiddleware: <T>(
19
+ point: HookPoint,
20
+ fn: (data: T) => Promise<T> | T,
21
+ pluginId: string,
22
+ weight = 0
23
+ ) => {
17
24
  registry.registerMiddleware(point, fn, pluginId, weight);
18
25
  },
19
26
  getDeviceId: getStableDeviceId,
20
27
  registerSlot: (
21
28
  slotName: SlotName,
22
- component: React.ComponentType<any>,
29
+ component: React.ComponentType<IComPropsRegisteredToSlot>,
23
30
  pluginId: string,
24
31
  weight = 0
25
32
  ) => {
@@ -54,14 +61,16 @@ class PluginManager {
54
61
  }
55
62
 
56
63
  try {
57
- const module = await moduleLoader();
64
+ const module = (await moduleLoader()) as {
65
+ default: IPlugin;
66
+ };
58
67
 
59
68
  const p: IPlugin = module.default;
60
69
 
61
70
  const ctx = this.createHostContext();
62
71
 
63
72
  if (p.onInstall) {
64
- p.onInstall(ctx);
73
+ await p.onInstall(ctx);
65
74
  }
66
75
 
67
76
  this.activePlugins.set(pluginId, p);
@@ -1,15 +1,17 @@
1
- import type { SlotName, HookPoint } from 'src/types/slots';
1
+ import React from 'react';
2
+
3
+ import type { SlotName, HookPoint, IComPropsRegisteredToSlot } from '#/types/slots';
2
4
 
3
5
  export interface ISlotEntry {
4
6
  id: string;
5
- component: React.ComponentType<any>;
7
+ component: React.ComponentType<IComPropsRegisteredToSlot>;
6
8
  pluginId: string;
7
9
  weight: number;
8
10
  }
9
11
 
10
- export interface IMiddlewareEntry {
12
+ export interface IMiddlewareEntry<T> {
11
13
  id: string;
12
- fn: Function;
14
+ fn: (data: T) => Promise<T> | T;
13
15
  pluginId: string;
14
16
  weight?: number;
15
17
  }
@@ -18,19 +20,41 @@ export class Registry {
18
20
  private slots = new Map<SlotName, ISlotEntry[]>();
19
21
 
20
22
  private listeners = new Set<() => void>();
23
+ private middlewareListenerMap = new Map<HookPoint, Set<() => void>>();
21
24
 
22
- private middlewares = new Map<HookPoint, IMiddlewareEntry[]>();
25
+ private middlewares = new Map<HookPoint, IMiddlewareEntry<unknown>[]>();
23
26
 
24
27
  private broadcastChange() {
25
28
  this.listeners.forEach(listener => listener());
26
29
  }
27
30
 
31
+ private broadcastMiddlewareChange(point: HookPoint) {
32
+ const listeners = this.middlewareListenerMap.get(point);
33
+ if (listeners) {
34
+ listeners.forEach(listener => listener());
35
+ }
36
+ }
37
+
38
+ subscribeMiddleware(hookPoint: HookPoint, listener: () => void) {
39
+ if (!this.middlewareListenerMap.has(hookPoint)) {
40
+ this.middlewareListenerMap.set(hookPoint, new Set());
41
+ }
42
+ const listeners = this.middlewareListenerMap.get(hookPoint)!;
43
+ listeners.add(listener);
44
+ return () => listeners.delete(listener);
45
+ }
46
+
28
47
  subscribe(listener: () => void) {
29
48
  this.listeners.add(listener);
30
49
  return () => this.listeners.delete(listener);
31
50
  }
32
51
 
33
- registerComponent(slot: SlotName, component: React.ComponentType, pluginId: string, weight = 0) {
52
+ registerComponent(
53
+ slot: SlotName,
54
+ component: React.ComponentType<IComPropsRegisteredToSlot>,
55
+ pluginId: string,
56
+ weight = 0
57
+ ) {
34
58
  const existing = this.slots.get(slot) || [];
35
59
 
36
60
  const newEntry: ISlotEntry = {
@@ -65,10 +89,15 @@ export class Registry {
65
89
  this.broadcastChange();
66
90
  }
67
91
 
68
- registerMiddleware(hookPoint: HookPoint, fn: Function, pluginId: string, weight = 0) {
92
+ registerMiddleware<T>(
93
+ hookPoint: HookPoint,
94
+ fn: (data: T) => Promise<T> | T,
95
+ pluginId: string,
96
+ weight = 0
97
+ ) {
69
98
  const existing = this.middlewares.get(hookPoint) || [];
70
99
 
71
- const newEntry: IMiddlewareEntry = {
100
+ const newEntry: IMiddlewareEntry<T> = {
72
101
  id: `${pluginId}-${fn.name || 'middleware'}`,
73
102
  pluginId,
74
103
  fn,
@@ -76,11 +105,16 @@ export class Registry {
76
105
  };
77
106
 
78
107
  // 插入并按权重排序(权重大的在前)
79
- const newList = [...existing, newEntry].sort((a, b) => (b.weight || 0) - (a.weight || 0));
108
+ const newList = [...existing, newEntry as IMiddlewareEntry<unknown>].sort(
109
+ (a, b) => (b.weight || 0) - (a.weight || 0)
110
+ );
111
+
80
112
  this.middlewares.set(hookPoint, newList);
113
+
114
+ this.broadcastMiddlewareChange(hookPoint);
81
115
  }
82
116
 
83
- getComponents(slotName: SlotName): React.ComponentType<any>[] {
117
+ getComponents(slotName: SlotName): React.ComponentType<IComPropsRegisteredToSlot>[] {
84
118
  return (this.slots.get(slotName) || []).map(entry => entry.component);
85
119
  }
86
120
 
@@ -88,7 +122,7 @@ export class Registry {
88
122
  const fns = (this.middlewares.get(point) || []).map(entry => entry.fn);
89
123
  let result = data;
90
124
  for (const fn of fns) {
91
- result = await fn(result);
125
+ result = (await fn(result)) as T;
92
126
  }
93
127
  return result;
94
128
  }
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { PathRouteProps } from 'react-router-dom';
3
+
4
+ import { IComPropsRegisteredToSlot } from '#/types/slots';
5
+
6
+ export const ExtendedRoutesPage = ({ data }: IComPropsRegisteredToSlot) => {
7
+ const route = data as Omit<PathRouteProps, 'element'>;
8
+
9
+ if (route.path === '/hello') {
10
+ return <div className="p-4 text-center">Hello from Extra Entry Plugin!</div>;
11
+ }
12
+
13
+ return <></>;
14
+ };
@@ -0,0 +1,32 @@
1
+ import { IHostContext } from '#/types/hostApi';
2
+ import { IPlugin } from '#/types/plugin';
3
+ import { buildEntryCreator } from '#/utils';
4
+
5
+ import { ExtendedRoutesPage } from './components/page';
6
+
7
+ export class ExtraEntryPlugin implements IPlugin {
8
+ id: string = 'extra-entry';
9
+ name: string = 'Extra Entry';
10
+ description?: string | undefined;
11
+ version: string = '1.0.0';
12
+ author?: string | undefined = 'bbki.ng';
13
+
14
+ onInstall?: ((ctx: IHostContext) => void | Promise<void>) | undefined = async (
15
+ ctx: IHostContext
16
+ ) => {
17
+ const entryCreator = buildEntryCreator(ctx);
18
+ entryCreator(
19
+ {
20
+ pageComponent: ExtendedRoutesPage,
21
+ path: '/hello',
22
+ label: 'cd ./hello',
23
+ },
24
+ this.id
25
+ );
26
+ };
27
+
28
+ onDisable?: (() => Promise<void> | void) | undefined;
29
+ onDestroy?: (() => void) | undefined;
30
+ }
31
+
32
+ export default new ExtraEntryPlugin();
@@ -12,6 +12,12 @@ export const PLUGIN_MANIFEST = [
12
12
  description:
13
13
  'Provides additional change directory functionalities for enhanced user experience.',
14
14
  },
15
+ {
16
+ name: 'extra-entry',
17
+ id: 'extra-entry',
18
+ version: '0.1.0',
19
+ description: 'Provides extra entries for cover and extended routes.',
20
+ },
15
21
  {
16
22
  name: 'xwy',
17
23
  id: 'xwy',
@@ -1,23 +1,21 @@
1
- import { PathObj } from '@bbki.ng/ui';
2
1
  import React from 'react';
2
+ import { PathObj } from '@bbki.ng/ui';
3
3
 
4
- import { StickerCtx } from '../context';
4
+ import { IComPropsRegisteredToSlot } from '#/types/slots';
5
5
 
6
- export const StickerCom = ({ data }: { data: PathObj[] }) => {
7
- const ctx = StickerCtx.useCtx();
6
+ export const StickerCom = ({ data }: IComPropsRegisteredToSlot) => {
7
+ const paths = data as PathObj[];
8
8
 
9
- if (data.length === 0) {
9
+ if (paths.length === 0) {
10
10
  return null;
11
11
  }
12
12
 
13
- const lastPath = data[data.length - 1];
13
+ const lastPath = paths[paths.length - 1];
14
14
 
15
15
  if (lastPath.name !== '~') {
16
16
  return null;
17
17
  }
18
18
 
19
- console.log(ctx.deviceId);
20
-
21
19
  return (
22
20
  <div className="fixed bottom-32 left-16">
23
21
  <div className="-rotate-17 inline-flex">
@@ -1,6 +1,8 @@
1
- import React, { ReactNode } from 'react';
1
+ import React from 'react';
2
2
  import { useLocation } from 'react-router-dom';
3
3
 
4
+ import { IComPropsRegisteredToSlot } from '#/types/slots';
5
+
4
6
  export const Crows = () => {
5
7
  return (
6
8
  <svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -13,9 +15,11 @@ export const Crows = () => {
13
15
  );
14
16
  };
15
17
 
16
- export const XwyLogo = ({ data: defaultLogo }: { data: ReactNode }) => {
18
+ export const XwyLogo = ({ data }: IComPropsRegisteredToSlot) => {
17
19
  const location = useLocation();
18
20
 
21
+ const defaultLogo = data as React.ReactNode;
22
+
19
23
  if (decodeURIComponent(location.pathname).includes('小乌鸦')) {
20
24
  return <Crows />;
21
25
  }
@@ -9,7 +9,7 @@ export const FontRules: Array<FontRule> = [
9
9
  src: '/fonts/xwy.woff2',
10
10
  format: 'woff2',
11
11
  },
12
- extraCls: 'text-2xl',
12
+ extraCls: 'text-2xl w-[113px]',
13
13
  variant: 'special',
14
14
  },
15
15
  ];
@@ -2,7 +2,7 @@ import React from 'react';
2
2
 
3
3
  import { type FingerprintData } from '@/utils/fingerprints';
4
4
 
5
- import { HookPoint, SlotName } from './slots';
5
+ import { HookPoint, IComPropsRegisteredToSlot, SlotName } from './slots';
6
6
 
7
7
  export interface IHostApi {
8
8
  getDeviceId: () => Promise<{ id: string; fp: FingerprintData }>;
@@ -12,9 +12,9 @@ export interface IHostApi {
12
12
  pluginId: string,
13
13
  weight?: number
14
14
  ) => void;
15
- registerSlot: <T>(
15
+ registerSlot: (
16
16
  slotName: SlotName,
17
- component: React.ComponentType<T>,
17
+ component: React.ComponentType<IComPropsRegisteredToSlot>,
18
18
  pluginId: string,
19
19
  weight?: number
20
20
  ) => void;
@@ -1,3 +1,7 @@
1
+ import type React from 'react';
2
+
3
+ import { IComPropsRegisteredToSlot } from '#/types/slots';
4
+
1
5
  import { IHostContext } from './hostApi';
2
6
 
3
7
  export interface IPlugin {
@@ -12,4 +16,10 @@ export interface IPlugin {
12
16
  onDestroy?: () => void;
13
17
  }
14
18
 
15
- export type PluginID = 'sticker' | 'xwy' | 'extra-cd';
19
+ export type PluginID = 'sticker' | 'xwy' | 'extra-cd' | 'extra-entry';
20
+
21
+ export interface IPluginEntry {
22
+ path: string;
23
+ label?: string;
24
+ pageComponent: React.ComponentType<IComPropsRegisteredToSlot>;
25
+ }
@@ -5,3 +5,12 @@ export interface TitleListItem {
5
5
  className?: string;
6
6
  variant?: 'default' | 'special';
7
7
  }
8
+
9
+ export interface IPost {
10
+ id: string;
11
+ title: string;
12
+ content: string;
13
+ author: string;
14
+ createdAt: string;
15
+ updatedAt: string;
16
+ }
@@ -1,2 +1,12 @@
1
- export type SlotName = 'leftCol' | 'rightCol' | 'articleActionRow' | 'logo';
2
- export type HookPoint = 'filterPosts' | 'transformPostContent' | 'transformTitleList';
1
+ export type SlotName = 'leftCol' | 'rightCol' | 'articleActionRow' | 'logo' | 'route';
2
+
3
+ export type HookPoint =
4
+ | 'filterPosts'
5
+ | 'transformPostContent'
6
+ | 'transformTitleList'
7
+ | 'extendedRoutes'
8
+ | 'transformCoverEntry';
9
+
10
+ export interface IComPropsRegisteredToSlot {
11
+ data: unknown;
12
+ }
@@ -0,0 +1,52 @@
1
+ import { LinkProps, PathRouteProps } from 'react-router-dom';
2
+ import React from 'react';
3
+
4
+ import { IHostContext } from '#/types/hostApi';
5
+ import { IPluginEntry } from '#/types/plugin';
6
+ import { IComPropsRegisteredToSlot } from '#/types/slots';
7
+
8
+ export const buildEntryCreator = (ctx: IHostContext) => (entry: IPluginEntry, id: string) => {
9
+ ctx.api.registerMiddleware(
10
+ 'extendedRoutes',
11
+ (routes: Array<Omit<PathRouteProps, 'element'>>) => {
12
+ return [
13
+ ...routes,
14
+ {
15
+ path: entry.path,
16
+ },
17
+ ];
18
+ },
19
+ id,
20
+ 10
21
+ );
22
+
23
+ ctx.api.registerSlot(
24
+ 'route',
25
+ (props: IComPropsRegisteredToSlot) => {
26
+ const route = props.data as Omit<PathRouteProps, 'element'>;
27
+ if (route.path === entry.path) {
28
+ const Com = entry.pageComponent;
29
+ return <Com data={props.data} />;
30
+ }
31
+ return null;
32
+ },
33
+ id
34
+ );
35
+
36
+ if (!entry.label) return;
37
+
38
+ ctx.api.registerMiddleware(
39
+ 'transformCoverEntry',
40
+ (entries: Array<LinkProps>) => {
41
+ return [
42
+ ...entries,
43
+ {
44
+ to: entry.path,
45
+ children: entry.label,
46
+ },
47
+ ];
48
+ },
49
+ id,
50
+ 10
51
+ );
52
+ };
package/tsconfig.json CHANGED
@@ -5,11 +5,9 @@
5
5
  "jsx": "react",
6
6
  "noEmit": true,
7
7
  "moduleResolution": "bundler",
8
- "ignoreDeprecations": "6.0",
9
- "baseUrl": ".",
10
8
  "paths": {
11
- "@/*": ["src/blog/*"],
12
- "#/*": ["src/*"]
9
+ "@/*": ["./src/blog/*"],
10
+ "#/*": ["./src/*"]
13
11
  }
14
12
  },
15
13
  "include": ["./src", "vite.config.js", "index.d.ts"]
@@ -1,13 +0,0 @@
1
- import { Role, useRole } from '@/hooks/use_role';
2
- import React from 'react';
3
- import { Navigate } from 'react-router-dom';
4
-
5
- export const Auth = (props: { children: any; shouldRedirect?: boolean; role?: Role[] }) => {
6
- const myRole = useRole();
7
-
8
- if (props.role && !props.role.includes(myRole)) {
9
- return props.shouldRedirect ? <Navigate to={'/login'} /> : null;
10
- }
11
-
12
- return props.children;
13
- };
@@ -1,28 +0,0 @@
1
- import React, { useEffect } from 'react';
2
- import cls from 'classnames';
3
-
4
- export type DelayFadeInProps = {
5
- children: any;
6
- delay: number;
7
- };
8
-
9
- export const DelayFadeIn = (props: DelayFadeInProps) => {
10
- const [show, setShow] = React.useState(false);
11
-
12
- useEffect(() => {
13
- const id = setTimeout(() => {
14
- setShow(true);
15
- }, props.delay);
16
-
17
- return () => {
18
- clearTimeout(id);
19
- };
20
- }, []);
21
-
22
- const className = cls('transition-opacity', {
23
- 'opacity-100': show,
24
- 'opacity-0': !show,
25
- });
26
-
27
- return <div className={className}>{props.children}</div>;
28
- };
@@ -1,10 +0,0 @@
1
- import React from 'react';
2
- import { useGlobalLoading } from '@/hooks';
3
-
4
- export const Spinner = (props: { disableDotIndicator?: boolean }) => {
5
- const { disableDotIndicator } = props;
6
-
7
- useGlobalLoading('spinner', !disableDotIndicator);
8
-
9
- return <div className="h-full w-full grid place-items-center"></div>;
10
- };
@@ -1,11 +0,0 @@
1
- import React, { ReactElement, ReactNode, Suspense } from 'react';
2
- import { ErrorBoundary } from '@bbki.ng/ui';
3
- import { Spinner } from './Spinner';
4
-
5
- export const MySuspense = (props: { children: ReactNode; fallback?: ReactElement }) => {
6
- return (
7
- <ErrorBoundary>
8
- <Suspense fallback={<Spinner />}>{props.children}</Suspense>
9
- </ErrorBoundary>
10
- );
11
- };