@bbki.ng/site 2.0.34 → 2.0.36

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @bbki.ng/site
2
2
 
3
+ ## 2.0.36
4
+
5
+ ## 2.0.35
6
+
3
7
  ## 2.0.34
4
8
 
5
9
  ## 2.0.33
package/index.html CHANGED
@@ -38,6 +38,7 @@
38
38
  href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC&display=swap"
39
39
  rel="stylesheet"
40
40
  />
41
+ <script src="https://unpkg.com/open-heart-element" type="module"></script>
41
42
  </head>
42
43
 
43
44
  <body class="h-full m-0 flex flex-col font-mono">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbki.ng/site",
3
- "version": "2.0.34",
3
+ "version": "2.0.36",
4
4
  "description": "code behind bbki.ng",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@extism/extism": "2.0.0-rc11",
20
- "@bbki.ng/components": "workspace:2.6.8",
20
+ "@bbki.ng/components": "workspace:2.6.9",
21
21
  "@supabase/supabase-js": "^1.35.4",
22
22
  "classnames": "2.3.1",
23
23
  "react": "^18.0.0",
package/src/blog/app.tsx CHANGED
@@ -26,6 +26,7 @@ import { PluginContentPage } from "@/components/plugin/PluginContentPage";
26
26
  import { PluginRoutes } from "@/components/plugin/PluginRoutes";
27
27
  import { useClipboardToPost } from "@/hooks/use_clipboard_to_post";
28
28
  import { useSharedStringToPost } from "@/hooks/use_shared_string_to_post";
29
+ import { ThreeColLayout, ErrorBoundary } from "@bbki.ng/components";
29
30
 
30
31
  const Layout = () => {
31
32
  const { isLoading, isFontLoading } = useContext(GlobalLoadingContext);
@@ -45,19 +46,21 @@ const Layout = () => {
45
46
  />
46
47
  </AppCtxMenu>
47
48
  }
48
- main={<Outlet />}
49
+ main={
50
+ <ThreeColLayout
51
+ middleRenderer={() => {
52
+ return (
53
+ <ErrorBoundary>
54
+ <Outlet />
55
+ </ErrorBoundary>
56
+ );
57
+ }}
58
+ />
59
+ }
49
60
  />
50
61
  );
51
62
  };
52
63
 
53
- const NowInMidCol = threeColWrapper(NowPage);
54
- const ContentInMidCol = threeColWrapper(Txt);
55
- const ArticleInMidCol = threeColWrapper(ArticlePage);
56
- const TagsInMidCol = threeColWrapper(Tags);
57
- const LoginInMidCol = threeColWrapper(Login);
58
- const TagsResultInMidCol = threeColWrapper(TagsResult);
59
- const CoverInMidCol = threeColWrapper(Cover);
60
-
61
64
  export const App = () => {
62
65
  useClipboardToPost();
63
66
 
@@ -69,25 +72,18 @@ export const App = () => {
69
72
  <BBContext>
70
73
  <Routes>
71
74
  <Route path="/" element={<Layout />}>
72
- <Route index element={<CoverInMidCol />} />
75
+ <Route index element={<Cover />} />
73
76
 
74
77
  <Route path="blog" element={<Outlet />}>
75
- <Route path="" element={<ContentInMidCol />} />
76
- <Route path=":title" element={<ArticleInMidCol />} />
78
+ <Route path="" element={<Txt />} />
79
+ <Route path=":title" element={<ArticlePage />} />
77
80
  </Route>
78
- <Route path="blog/:title/:id" element={<PhotoProjects />} />
79
- <Route path="tags" element={<TagsInMidCol />} />
80
- <Route path="tags/:tag" element={<TagsResultInMidCol />} />
81
+
82
+ <Route path="tags" element={<Tags />} />
83
+ <Route path="tags/:tag" element={<TagsResult />} />
81
84
 
82
85
  <Route path="bot" element={<BotRedirect />} />
83
- <Route path="now" element={<NowInMidCol />} />
84
- <Route path="login" element={<LoginInMidCol />} />
85
- <Route path="upload" element={<UploadPage />} />
86
- <Route path="/plugins" element={<PluginRoutes />} />
87
- <Route
88
- path="/plugins/:pluginRoute"
89
- element={<PluginContentPage />}
90
- />
86
+ <Route path="login" element={<Login />} />
91
87
  </Route>
92
88
  <Route path="*" element={<NotFound />} />
93
89
  </Routes>
@@ -4,6 +4,7 @@ import { ROUTES } from "@/constants";
4
4
  import classNames from "classnames";
5
5
  import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
6
6
  import { useSafeArticleLoading } from "@/hooks/use_safe_loading";
7
+ import { OpenHeartReaction } from "../oh_reaction";
7
8
 
8
9
  export type ArticlePageProps = {
9
10
  tags?: string[];
@@ -29,7 +30,7 @@ export const ArticlePage = (props: ArticlePageProps) => {
29
30
  }
30
31
 
31
32
  const articleCls = classNames("prose", {
32
- "mb-20": tagNames,
33
+ "mb-20": true,
33
34
  });
34
35
 
35
36
  return (
@@ -42,7 +43,10 @@ export const ArticlePage = (props: ArticlePageProps) => {
42
43
  >
43
44
  <article className={articleCls}>{props.children}</article>
44
45
  </Article>
45
- <span className="p-16">{<Tags tags={allTags} />}</span>
46
+ <div className="p-16">
47
+ <span>{<Tags tags={allTags} />}</span>
48
+ <OpenHeartReaction title={title} />
49
+ </div>
46
50
  </>
47
51
  );
48
52
  };
@@ -0,0 +1,118 @@
1
+ import React, {
2
+ ReactNode,
3
+ useContext,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from "react";
8
+ import { BlinkDot } from "@bbki.ng/components";
9
+ import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
10
+
11
+ declare global {
12
+ namespace JSX {
13
+ interface IntrinsicElements {
14
+ "open-heart": React.DetailedHTMLProps<
15
+ React.HTMLAttributes<HTMLElement> & {
16
+ href?: string;
17
+ emoji?: string;
18
+ ariaDisabled?: boolean;
19
+ onClick?: React.MouseEventHandler<HTMLElement>;
20
+ },
21
+ HTMLElement
22
+ >;
23
+ }
24
+ }
25
+ }
26
+
27
+ const HEART_SIZE = 12;
28
+
29
+ const heart = (
30
+ <svg
31
+ data-testid="geist-icon"
32
+ height={HEART_SIZE}
33
+ width={HEART_SIZE}
34
+ stroke-linejoin="round"
35
+ // style={{ color: "#fecaca" }}
36
+ className="text-gray-400 hover:text-red-400 transition-colors ease-in duration-200"
37
+ viewBox="0 0 16 16"
38
+ >
39
+ <path
40
+ fill-rule="evenodd"
41
+ clip-rule="evenodd"
42
+ d="M7.06463 3.20474C5.79164 1.93175 3.72772 1.93175 2.45474 3.20474C1.18175 4.47773 1.18175 6.54166 2.45474 7.81465L8 13.3599L13.5453 7.81465C14.8182 6.54166 14.8182 4.47773 13.5453 3.20474C12.2723 1.93175 10.2084 1.93175 8.93537 3.20474L8.53033 3.60979L8 4.14012L7.46967 3.60979L7.06463 3.20474ZM8 2.02321C6.13348 0.286219 3.21165 0.326509 1.39408 2.14408C-0.464694 4.00286 -0.464691 7.01653 1.39408 8.87531L7.46967 14.9509L8 15.4812L8.53033 14.9509L14.6059 8.87531C16.4647 7.01653 16.4647 4.00286 14.6059 2.14408C12.7884 0.326509 9.86653 0.286221 8 2.02321Z"
43
+ fill="currentColor"
44
+ ></path>
45
+ </svg>
46
+ );
47
+
48
+ const heartFill = (
49
+ <svg
50
+ data-testid="geist-icon"
51
+ height={HEART_SIZE}
52
+ width={HEART_SIZE}
53
+ stroke-linejoin="round"
54
+ className="text-red-400"
55
+ viewBox={`0 0 16 16`}
56
+ >
57
+ <path
58
+ d="M1.39408 2.14408C3.21165 0.326509 6.13348 0.286219 8 2.02321C9.86652 0.286221 12.7884 0.326509 14.6059 2.14408C16.4647 4.00286 16.4647 7.01653 14.6059 8.87531L8 15.4812L1.39408 8.87531C-0.464691 7.01653 -0.464694 4.00286 1.39408 2.14408Z"
59
+ fill="currentColor"
60
+ ></path>
61
+ </svg>
62
+ );
63
+
64
+ const useHeartSent = () => {
65
+ const [sent, setSent] = useState(false);
66
+ const { setIsLoading } = useContext(GlobalLoadingContext);
67
+
68
+ const handleSent = () => {
69
+ console.log("heart sent");
70
+ setSent(true);
71
+ setIsLoading(false);
72
+ };
73
+
74
+ useEffect(() => {
75
+ addEventListener("open-heart", handleSent);
76
+
77
+ return () => {
78
+ removeEventListener("open-heart", handleSent);
79
+ };
80
+ }, []);
81
+
82
+ return sent;
83
+ };
84
+
85
+ export const OpenHeartReaction = (props: { title: string }) => {
86
+ const { title } = props;
87
+ const sent = useHeartSent();
88
+
89
+ const { setIsLoading } = useContext(GlobalLoadingContext);
90
+
91
+ const ohRef = useRef<HTMLElement>(null);
92
+
93
+ const pressed = () => ohRef.current?.getAttribute("aria-pressed");
94
+
95
+ const handleHeartClick = () => {
96
+ if (sent || pressed()) {
97
+ return;
98
+ }
99
+
100
+ setIsLoading(true);
101
+ };
102
+
103
+ return (
104
+ <open-heart
105
+ style={{
106
+ display: "flex",
107
+ padding: 4,
108
+ marginTop: "1rem",
109
+ }}
110
+ ref={ohRef}
111
+ href={`https://oh.bbking.workers.dev/?id=${title}`}
112
+ emoji="❤️"
113
+ onClick={handleHeartClick}
114
+ >
115
+ {sent || pressed() ? heartFill : heart}
116
+ </open-heart>
117
+ );
118
+ };
@@ -49,4 +49,4 @@ const ContentPage = (props: PluginContentPageProps) => {
49
49
  );
50
50
  };
51
51
 
52
- export const PluginContentPage = threeColWrapper(ContentPage);
52
+ export const PluginContentPage = ContentPage;
@@ -20,4 +20,4 @@ const PluginRoutesContent = () => {
20
20
  );
21
21
  };
22
22
 
23
- export const PluginRoutes = threeColWrapper(PluginRoutesContent);
23
+ export const PluginRoutes = PluginRoutesContent;
@@ -25,5 +25,5 @@ export const useSafeArticleLoading = (safeSec: number, timeOutSec: number) => {
25
25
  return false;
26
26
  }
27
27
 
28
- return isLoading || isFontLoading || isArticleLoading;
28
+ return isFontLoading || isArticleLoading;
29
29
  };
@@ -3,7 +3,7 @@ import { CenterLinkList } from "@/components";
3
3
  import { EffectLayer } from "@/components/effect-layer/EffectLayer";
4
4
  import { GlobalRoutesContext } from "@/context/global_routes_provider";
5
5
 
6
- export const Cover = (props: { className: string }) => {
6
+ export const Cover = (props: { className?: string }) => {
7
7
  const globalRouteCtx = useContext(GlobalRoutesContext);
8
8
  const routes = globalRouteCtx.globalRoutes;
9
9
  const pluginEntry =
@@ -36,4 +36,4 @@ const Upload = () => {
36
36
  );
37
37
  };
38
38
 
39
- export const UploadPage = threeColWrapper(Upload);
39
+ export const UploadPage = Upload;
package/src/index.tsx CHANGED
@@ -1,4 +1,5 @@
1
1
  import { RenderBlogInto } from "./blog";
2
2
 
3
3
  const blogContainer = document.getElementById("blog") as Element;
4
+
4
5
  RenderBlogInto(blogContainer);