@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
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @bbki.ng/site
2
2
 
3
+ ## 5.5.20
4
+
5
+ ### Patch Changes
6
+
7
+ - 6748bb3: fix null pointer exception
8
+
9
+ ## 5.5.19
10
+
11
+ ### Patch Changes
12
+
13
+ - 3edea98: fix base url config
14
+ - Updated dependencies [3edea98]
15
+ - @bbki.ng/ui@0.2.13
16
+
3
17
  ## 5.5.18
4
18
 
5
19
  ### Patch Changes
package/index.d.ts CHANGED
@@ -1,12 +1,11 @@
1
- import React from 'react';
1
+ /// <reference types="vite/client" />
2
2
 
3
- declare const GLOBAL_BBKING_VERSION: string;
4
- declare const GLOBAL_COMMIT_HASH: string;
5
- interface ImportMeta {
6
- glob: (pattern: string) => Record<string, () => Promise<unknown>>;
7
- }
3
+ import type React from 'react';
8
4
 
9
5
  declare global {
6
+ const GLOBAL_BBKING_VERSION: string;
7
+ const GLOBAL_COMMIT_HASH: string;
8
+
10
9
  namespace JSX {
11
10
  interface IntrinsicElements {
12
11
  'bb-img': React.DetailedHTMLProps<
@@ -16,3 +15,5 @@ declare global {
16
15
  }
17
16
  }
18
17
  }
18
+
19
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbki.ng/site",
3
- "version": "5.5.18",
3
+ "version": "5.5.20",
4
4
  "description": "code behind bbki.ng",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -14,7 +14,7 @@
14
14
  "react-dom": "^18.0.0",
15
15
  "react-router-dom": "6",
16
16
  "swr": "^2.2.5",
17
- "@bbki.ng/ui": "0.2.12"
17
+ "@bbki.ng/ui": "0.2.13"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@eslint/compat": "^1.0.0",
@@ -57,7 +57,7 @@
57
57
  "vite-plugin-mdx": "^3.5.8",
58
58
  "vite-plugin-pwa": "0.19",
59
59
  "workbox-window": "^6.3.0",
60
- "@bbki.ng/config": "1.0.8"
60
+ "@bbki.ng/config": "1.0.9"
61
61
  },
62
62
  "author": "bbbottle",
63
63
  "license": "MIT",
package/src/blog/app.tsx CHANGED
@@ -1,75 +1,32 @@
1
- import React, { useContext } from 'react';
2
- import { Outlet, Route, Routes, useNavigate } from 'react-router-dom';
3
- import { Logo, Nav, NotFound, Page, Grid, ErrorBoundary, Container } from '@bbki.ng/ui';
1
+ import React from 'react';
2
+ import { Outlet, Route, Routes } from 'react-router-dom';
3
+ import { NotFound } from '@bbki.ng/ui';
4
4
 
5
- import { usePaths } from '@/hooks';
6
5
  import ArticlePage from '@/pages/extensions/txt/article';
7
6
  import Txt from '@/pages/extensions/txt';
8
- import { GlobalLoadingContext } from '@/context/global_loading_state_provider';
9
7
  import { BotRedirect } from '@/pages/bot';
10
8
  import { BBContext } from '@/context/bbcontext';
11
9
  import { Slot } from '#/core/components/SlotComp';
12
10
  import { usePlugins } from '#/core/hooks/use_plugins';
13
11
  import { SWR } from '@/swr';
12
+ import type { PluginID } from '#/types/plugin';
14
13
 
15
14
  import { Cover, Streaming } from './pages';
15
+ import { usePluginEntries } from './hooks/use_plugin_entries';
16
+ import { BaseLayout } from './components/BaseLayout';
16
17
 
17
- const Layout = () => {
18
- const paths = usePaths();
19
- const { isLoading } = useContext(GlobalLoadingContext);
20
-
21
- const nav = useNavigate();
22
-
23
- const defaultLogo = (
24
- <Logo className="mr-2 cursor-pointer hover:opacity-80" onClick={() => nav('/')} />
25
- );
26
-
27
- return (
28
- <Page
29
- nav={
30
- <Nav
31
- paths={paths}
32
- className="gradient-blur-cover select-none"
33
- loading={isLoading}
34
- customLogo={<Slot name="logo" data={defaultLogo} placeholder={defaultLogo} />}
35
- style={{
36
- paddingTop: 'var(--safe-top)',
37
- transition: 'all .2s ease-in-out',
38
- }}
39
- />
40
- }
41
- main={
42
- <Grid
43
- leftAside={
44
- <div className="py-32 px-6">
45
- <Slot name="leftCol" data={paths} />
46
- </div>
47
- }
48
- rightAside={
49
- <div className="py-32 px-6">
50
- <Slot name="rightCol" data={paths} />
51
- </div>
52
- }
53
- >
54
- <Container className="py-32">
55
- <ErrorBoundary>
56
- <Outlet />
57
- </ErrorBoundary>
58
- </Container>
59
- </Grid>
60
- }
61
- />
62
- );
63
- };
18
+ const APP_PLUGIN_IDS: Array<PluginID> = ['sticker', 'xwy', 'extra-cd' /*'extra-entry'*/];
64
19
 
65
20
  export const App = () => {
66
- usePlugins(['sticker', 'xwy', 'extra-cd']);
21
+ usePlugins(APP_PLUGIN_IDS);
22
+
23
+ const pluginEntries = usePluginEntries();
67
24
 
68
25
  return (
69
26
  <SWR>
70
27
  <BBContext>
71
28
  <Routes>
72
- <Route path="/" element={<Layout />}>
29
+ <Route path="/" element={<BaseLayout />}>
73
30
  <Route index element={<Cover />} />
74
31
 
75
32
  <Route path="blog" element={<Outlet />}>
@@ -79,6 +36,13 @@ export const App = () => {
79
36
 
80
37
  <Route path="bot" element={<BotRedirect />} />
81
38
  <Route path="now" element={<Streaming />} />
39
+ {pluginEntries?.map(route => (
40
+ <Route
41
+ key={route.path}
42
+ path={route.path}
43
+ element={<Slot name="route" data={route} />}
44
+ />
45
+ ))}
82
46
  </Route>
83
47
  <Route path="*" element={<NotFound />} />
84
48
  </Routes>
@@ -0,0 +1,55 @@
1
+ import React, { useContext } from 'react';
2
+ import { useNavigate, Outlet } from 'react-router-dom';
3
+ import { Logo, Nav, Page, Grid, ErrorBoundary, Container } from '@bbki.ng/ui';
4
+
5
+ import { Slot } from '#/core/components/SlotComp';
6
+ import { usePaths } from '@/hooks';
7
+ import { GlobalLoadingContext } from '@/context/global_loading_state_provider';
8
+
9
+ export const BaseLayout = () => {
10
+ const paths = usePaths();
11
+ const { isLoading } = useContext(GlobalLoadingContext);
12
+
13
+ const nav = useNavigate();
14
+
15
+ const defaultLogo = (
16
+ <Logo className="mr-2 cursor-pointer hover:opacity-80" onClick={() => nav('/')} />
17
+ );
18
+
19
+ return (
20
+ <Page
21
+ nav={
22
+ <Nav
23
+ paths={paths}
24
+ className="gradient-blur-cover select-none"
25
+ loading={isLoading}
26
+ customLogo={<Slot name="logo" data={defaultLogo} placeholder={defaultLogo} />}
27
+ style={{
28
+ paddingTop: 'var(--safe-top)',
29
+ transition: 'all .2s ease-in-out',
30
+ }}
31
+ />
32
+ }
33
+ main={
34
+ <Grid
35
+ leftAside={
36
+ <div className="py-32 px-6">
37
+ <Slot name="leftCol" data={paths} />
38
+ </div>
39
+ }
40
+ rightAside={
41
+ <div className="py-32 px-6">
42
+ <Slot name="rightCol" data={paths} />
43
+ </div>
44
+ }
45
+ >
46
+ <Container className="py-32">
47
+ <ErrorBoundary>
48
+ <Outlet />
49
+ </ErrorBoundary>
50
+ </Container>
51
+ </Grid>
52
+ }
53
+ />
54
+ );
55
+ };
@@ -1,9 +1,7 @@
1
1
  import React from 'react';
2
- import { LinkList } from '@bbki.ng/ui';
2
+ import { LinkList, LinkListProps } from '@bbki.ng/ui';
3
3
 
4
- export { MySuspense } from './my_suspense';
5
-
6
- export const CenterLinkList = (props: any) => {
4
+ export const CenterLinkList = (props: LinkListProps) => {
7
5
  return (
8
6
  <div className="flex justify-center relative h-full">
9
7
  <LinkList {...props} />
@@ -1,19 +1,15 @@
1
1
  import React, { createContext, ReactNode, useState, useCallback, useMemo } from 'react';
2
2
 
3
- import { useFontLoading } from '@/hooks/use_font_loading';
4
-
5
3
  type LoadingStates = Map<string, boolean>;
6
4
 
7
5
  type LoadingContext = {
8
6
  isLoading: boolean;
9
- isFontLoading: boolean;
10
7
  register: (id: string) => void;
11
8
  setLoading: (id: string, loading: boolean) => void;
12
9
  unregister: (id: string) => void;
13
10
  };
14
11
 
15
12
  export const GlobalLoadingContext = createContext<LoadingContext>({
16
- isFontLoading: false,
17
13
  isLoading: false,
18
14
  register: () => {},
19
15
  setLoading: () => {},
@@ -22,7 +18,6 @@ export const GlobalLoadingContext = createContext<LoadingContext>({
22
18
 
23
19
  export const GlobalLoadingStateProvider = (props: { children: ReactNode }) => {
24
20
  const [loadingStates, setLoadingStates] = useState<LoadingStates>(new Map());
25
- const isFontLoading = useFontLoading();
26
21
 
27
22
  const register = useCallback((id: string) => {
28
23
  setLoadingStates(prev => {
@@ -49,18 +44,17 @@ export const GlobalLoadingStateProvider = (props: { children: ReactNode }) => {
49
44
  }, []);
50
45
 
51
46
  const isLoading = useMemo(() => {
52
- return Array.from(loadingStates.values()).some(Boolean) || isFontLoading;
53
- }, [loadingStates, isFontLoading]);
47
+ return Array.from(loadingStates.values()).some(Boolean);
48
+ }, [loadingStates]);
54
49
 
55
50
  const contextValue = useMemo(
56
51
  () => ({
57
52
  isLoading,
58
- isFontLoading,
59
53
  register,
60
54
  setLoading,
61
55
  unregister,
62
56
  }),
63
- [isLoading, isFontLoading, register, setLoading, unregister]
57
+ [isLoading, register, setLoading, unregister]
64
58
  );
65
59
 
66
60
  return (
@@ -20,7 +20,7 @@ export function useGlobalLoading(id: string | undefined, loading: boolean | unde
20
20
  return () => {
21
21
  unregister(id);
22
22
  };
23
- }, [id, loading]);
23
+ }, [id, loading, register, setLoading, unregister]);
24
24
 
25
25
  return isLoading;
26
26
  }
@@ -0,0 +1,48 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { type PathRouteProps } from 'react-router-dom';
3
+
4
+ import { useMiddlewareRunner } from '#/core/hooks';
5
+
6
+ const protectedRoutesSet = new Set<string>([
7
+ '/bot',
8
+ '/now',
9
+ '/',
10
+ '/blog',
11
+ '/blog/:title',
12
+ 'default',
13
+ ]);
14
+
15
+ type PluginRoute = Omit<PathRouteProps, 'element'>;
16
+
17
+ export const usePluginEntries = () => {
18
+ const [fullRoutes, setFullRoutes] = useState<Array<PluginRoute>>([]);
19
+ const runRef = useRef<(input: Array<PluginRoute>) => Promise<Array<PluginRoute>>>(() =>
20
+ Promise.resolve([])
21
+ );
22
+
23
+ const onMiddlewareChange = useCallback(() => {
24
+ runRef.current([]).then(setFullRoutes);
25
+ }, []);
26
+
27
+ const { run } = useMiddlewareRunner<Array<PluginRoute>>({
28
+ hookPoint: 'extendedRoutes',
29
+ onMiddlewareChange,
30
+ });
31
+
32
+ runRef.current = run;
33
+
34
+ useEffect(() => {
35
+ run([]).then(setFullRoutes);
36
+ }, [run]);
37
+
38
+ const safeRoutes = fullRoutes?.filter(route => {
39
+ if ('path' in route) {
40
+ return !protectedRoutesSet.has(route.path);
41
+ }
42
+ return false;
43
+ }) as Array<PluginRoute>;
44
+
45
+ console.log('safe plugin routes:', safeRoutes);
46
+
47
+ return safeRoutes ?? [];
48
+ };
@@ -1,10 +1,11 @@
1
1
  import useSWR from 'swr';
2
- import { useMemo } from 'react';
2
+ import { useEffect, useMemo, useState } from 'react';
3
3
 
4
4
  import { useGlobalLoading } from '@/hooks';
5
5
  import { baseFetcher } from '@/utils';
6
6
  import { API_ENDPOINT } from '@/constants/routes';
7
- import { useMiddlewareTransData } from '#/core/hooks';
7
+ import { IPost } from '#/types/posts';
8
+ import { useMiddlewareRunner } from '#/core/hooks/useMiddlewareTransData';
8
9
 
9
10
  const isProd = true;
10
11
  const POSTS_API = !isProd ? '/api/posts' : `${API_ENDPOINT}/posts`;
@@ -28,34 +29,40 @@ export const usePosts = (name: string = '', suspense?: boolean) => {
28
29
  const baseTitleList: TitleListItem[] = useMemo(() => {
29
30
  if (!data || swrError) return [];
30
31
 
31
- return data.map((p: any) => ({
32
+ return data.map((p: IPost) => ({
32
33
  name: p.title,
33
34
  to: p.title,
34
35
  children: p.title,
35
36
  }));
36
37
  }, [data, swrError]);
37
38
 
39
+ const [fullTitleList, setFullTitleList] = useState<TitleListItem[]>(baseTitleList);
40
+
38
41
  // Use middleware hook to transform title list
39
42
  const {
40
- data: titleList,
41
43
  loading: isTransforming,
42
44
  error: transformError,
43
- } = useMiddlewareTransData({
45
+ run,
46
+ } = useMiddlewareRunner<TitleListItem[]>({
44
47
  hookPoint: 'transformTitleList',
45
- baseData: baseTitleList,
46
- immediate: baseTitleList.length > 0,
47
48
  });
48
49
 
50
+ useEffect(() => {
51
+ if (baseTitleList.length > 0) {
52
+ run(baseTitleList).then(setFullTitleList);
53
+ }
54
+ }, [baseTitleList, run]);
55
+
49
56
  const gLoading = useGlobalLoading('posts', isDataLoading || isTransforming);
50
57
 
51
58
  const posts =
52
59
  isDataLoading || name === '' || swrError || !data
53
60
  ? data
54
- : data.find((p: any) => p.title === name);
61
+ : data.find((p: IPost) => p.title === name);
55
62
 
56
63
  return {
57
64
  posts,
58
- titleList: titleList ?? [],
65
+ titleList: fullTitleList ?? [],
59
66
  isError: swrError || transformError,
60
67
  isLoading: gLoading,
61
68
  };
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { createRoot } from 'react-dom/client';
3
3
  import { BrowserRouter as Router } from 'react-router-dom';
4
+
4
5
  import App from './app';
5
6
  import './main.css';
6
7
 
@@ -1,31 +1,40 @@
1
- import React, { useContext } from 'react';
1
+ import React, { useEffect, useMemo } from 'react';
2
+ import { LinkProps } from '@bbki.ng/ui';
3
+
2
4
  import { CenterLinkList } from '@/components';
3
- import { GlobalRoutesContext } from '@/context/global_routes_provider';
5
+ import { useMiddlewareRunner } from '#/core/hooks';
6
+
7
+ export const Cover = (_: { className?: string }) => {
8
+ const baseEntries: Array<LinkProps> = useMemo(
9
+ () => [
10
+ {
11
+ to: '/blog',
12
+ children: 'cd ./blog',
13
+ },
14
+ {
15
+ to: '/now',
16
+ children: 'cd ./now',
17
+ },
18
+ ],
19
+ []
20
+ );
21
+
22
+ const [entries, setEntries] = React.useState<Array<LinkProps>>(baseEntries);
23
+
24
+ const { run } = useMiddlewareRunner<Array<LinkProps>>({
25
+ hookPoint: 'transformCoverEntry',
26
+ onMiddlewareChange: () => {
27
+ run(baseEntries).then(setEntries);
28
+ },
29
+ });
30
+
31
+ useEffect(() => {
32
+ run(baseEntries).then(setEntries);
33
+ }, [baseEntries, run]);
4
34
 
5
- export const Cover = (props: { className?: string }) => {
6
- const globalRouteCtx = useContext(GlobalRoutesContext);
7
- const routes = globalRouteCtx.globalRoutes;
8
- const pluginEntry = routes.length > 0 ? [{ to: '/plugins', name: 'cd ./plugins' }] : [];
9
35
  return (
10
36
  <>
11
- <CenterLinkList
12
- className="select-none"
13
- links={[
14
- {
15
- to: '/blog',
16
- name: 'cd ./blog',
17
- children: 'cd ./blog',
18
- },
19
- {
20
- to: '/now',
21
- name: 'cd ./now',
22
- children: 'cd ./now',
23
- },
24
- ...pluginEntry,
25
- ]}
26
- title=""
27
- // footer={<Version className="" />}
28
- />
37
+ <CenterLinkList className="select-none" links={entries} />
29
38
  </>
30
39
  );
31
40
  };
@@ -1,11 +1,12 @@
1
1
  import React from 'react';
2
2
  import { NotFound } from '@bbki.ng/ui';
3
3
  import { useParams } from 'react-router-dom';
4
+
4
5
  import { usePosts } from '@/hooks/use_posts';
5
6
  import { ArticlePage } from '@/components/article';
6
7
  import { useBlogScrollReset } from '@/hooks/use_blog_scroll_pos_restoration';
7
8
 
8
- export default () => {
9
+ function TxtArticle() {
9
10
  const { title } = useParams();
10
11
  const { posts, isError, isLoading } = usePosts(title);
11
12
 
@@ -19,7 +20,7 @@ export default () => {
19
20
  return <NotFound />;
20
21
  }
21
22
 
22
- if (isLoading) {
23
+ if (isLoading || !posts) {
23
24
  return null;
24
25
  }
25
26
 
@@ -30,4 +31,6 @@ export default () => {
30
31
  <div dangerouslySetInnerHTML={{ __html: posts.content }} />
31
32
  </ArticlePage>
32
33
  );
33
- };
34
+ }
35
+
36
+ export default TxtArticle;
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { LinkProps, Button } from '@bbki.ng/ui';
3
+
3
4
  import { usePosts } from '@/hooks/use_posts';
4
5
  import { CenterLinkList } from '@/components';
5
6
  import { useBlogScroll, useBlogScrollRestoration } from '@/hooks/use_blog_scroll_pos_restoration';
@@ -9,43 +10,46 @@ type TxtProps = {
9
10
  articleList?: LinkProps[];
10
11
  };
11
12
 
12
- export default (props: TxtProps) => {
13
- const { titleList, isLoading, isError } = usePosts();
13
+ const Txt = (props: TxtProps) => {
14
+ const { titleList, isError } = usePosts();
14
15
 
15
16
  useBlogScrollRestoration();
16
17
 
17
18
  const { gotoTop } = useBlogScroll();
18
19
 
19
- if (isLoading) {
20
- return null;
21
- }
22
-
23
20
  if (isError) {
24
- return <CenterLinkList links={props.articleList} />;
21
+ return <CenterLinkList links={props.articleList ?? titleList} />;
25
22
  }
26
23
 
24
+ const links = props.articleList ?? titleList;
25
+
27
26
  return (
28
27
  <CenterLinkList
29
- links={props.articleList || titleList}
30
- loading={isLoading}
28
+ links={links}
31
29
  footer={
32
- <Button onClick={gotoTop} className="mt-32">
33
- <svg
34
- data-testid="geist-icon"
35
- height="16"
36
- stroke-linejoin="round"
37
- viewBox="0 0 16 16"
38
- width="16"
39
- >
40
- <path
41
- fill-rule="evenodd"
42
- clip-rule="evenodd"
43
- d="M8.70711 1.39644C8.31659 1.00592 7.68342 1.00592 7.2929 1.39644L2.21968 6.46966L1.68935 6.99999L2.75001 8.06065L3.28034 7.53032L7.25001 3.56065V14.25V15H8.75001V14.25V3.56065L12.7197 7.53032L13.25 8.06065L14.3107 6.99999L13.7803 6.46966L8.70711 1.39644Z"
44
- fill="currentColor"
45
- ></path>
46
- </svg>
47
- </Button>
30
+ links.length > 0 ? (
31
+ <Button onClick={gotoTop} className="mt-32">
32
+ <svg
33
+ data-testid="geist-icon"
34
+ height="16"
35
+ strokeLinejoin="round"
36
+ viewBox="0 0 16 16"
37
+ width="16"
38
+ >
39
+ <path
40
+ fillRule="evenodd"
41
+ clipRule="evenodd"
42
+ d="M8.70711 1.39644C8.31659 1.00592 7.68342 1.00592 7.2929 1.39644L2.21968 6.46966L1.68935 6.99999L2.75001 8.06065L3.28034 7.53032L7.25001 3.56065V14.25V15H8.75001V14.25V3.56065L12.7197 7.53032L13.25 8.06065L14.3107 6.99999L13.7803 6.46966L8.70711 1.39644Z"
43
+ fill="currentColor"
44
+ ></path>
45
+ </svg>
46
+ </Button>
47
+ ) : null
48
48
  }
49
49
  />
50
50
  );
51
51
  };
52
+
53
+ Txt.displayName = 'Txt';
54
+
55
+ export default Txt;
package/src/blog/swr.tsx CHANGED
@@ -1,8 +1,9 @@
1
- import React from 'react';
1
+ import React, { ReactNode } from 'react';
2
2
  import { SWRConfig } from 'swr';
3
+
3
4
  import { cfApiFetcher } from '@/utils';
4
5
 
5
- export const SWR = (props: { children: any }) => {
6
+ export const SWR = (props: { children: ReactNode }) => {
6
7
  return (
7
8
  <SWRConfig
8
9
  value={{
@@ -1,11 +1,4 @@
1
- import { FunctionComponent } from 'react';
2
-
3
1
  export interface pathObj {
4
2
  path?: string;
5
3
  name: string;
6
4
  }
7
-
8
- export interface compPathObj extends pathObj {
9
- component: FunctionComponent<any>;
10
- componentProps?: any;
11
- }
@@ -32,24 +32,3 @@ export const withBBApi =
32
32
  fetcher(`${apiEndPoint}/${resource}`, { ...init, mode: 'cors' });
33
33
 
34
34
  export const cfApiFetcher = withBBApi(baseFetcher)(API_ENDPOINT);
35
-
36
- export const changeFont = (type: FontType) => {
37
- const rootDiv = document.getElementById('root');
38
- if (rootDiv == null) {
39
- return;
40
- }
41
-
42
- if (rootDiv.classList.contains(type)) {
43
- return;
44
- }
45
-
46
- // remove all font type class
47
- for (const fontType in FontType) {
48
- rootDiv.classList.remove(fontType);
49
- }
50
-
51
- rootDiv.classList.add(type);
52
-
53
- // save font type to local storage
54
- localStorage.setItem('font', type);
55
- };
@@ -1,5 +1,6 @@
1
1
  import React, { createContext, useContext, ComponentType } from 'react';
2
- import { IHostContext } from '#/types/hostApi';
2
+
3
+ import { IComPropsRegisteredToSlot } from '#/types/slots';
3
4
 
4
5
  /**
5
6
  * 创建插件专属的 Context 工具集
@@ -33,15 +34,19 @@ export function createPluginCtx<T>() {
33
34
  * const Enhanced = withCtx(picker, BaseComp)(ctx);
34
35
  * ctx.api.registerSlot('slotName', Enhanced, pluginId);
35
36
  */
36
- const withCtx = <P extends { data?: any }>(
37
+ const withCtx = <P extends IComPropsRegisteredToSlot>(
37
38
  ctx: T,
38
39
  Component: React.ComponentType<P>
39
40
  ): ComponentType<P> => {
40
- return (props: P) => (
41
- <Ctx.Provider value={ctx}>
42
- <Component {...props} />
43
- </Ctx.Provider>
44
- );
41
+ const WrappedComponent: React.FC<P> = props => {
42
+ return (
43
+ <Ctx.Provider value={ctx}>
44
+ <Component {...props} />
45
+ </Ctx.Provider>
46
+ );
47
+ };
48
+
49
+ return WrappedComponent;
45
50
  };
46
51
 
47
52
  return {