@bbki.ng/site 5.4.22 → 5.4.25

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 (100) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/index.html +12 -19
  3. package/package.json +5 -8
  4. package/src/blog/app.tsx +21 -33
  5. package/src/blog/components/article/index.tsx +8 -17
  6. package/src/blog/components/index.tsx +0 -6
  7. package/src/blog/components/share/share-btn.tsx +5 -8
  8. package/src/blog/constants/index.ts +1 -16
  9. package/src/blog/constants/routes.ts +12 -22
  10. package/src/blog/context/bbcontext.tsx +7 -7
  11. package/src/blog/hooks/index.ts +3 -18
  12. package/src/blog/hooks/use_dynamic_logo.tsx +6 -11
  13. package/src/blog/hooks/use_posts.ts +19 -10
  14. package/src/blog/hooks/use_role.ts +9 -14
  15. package/src/blog/hooks/use_streaming.ts +2 -2
  16. package/src/blog/index.tsx +5 -11
  17. package/src/blog/pages/cover/index.tsx +0 -1
  18. package/src/blog/pages/extensions/txt/article.tsx +7 -21
  19. package/src/blog/pages/extensions/txt/index.tsx +2 -17
  20. package/src/blog/pages/login/index.tsx +18 -42
  21. package/src/blog/pages/streaming/index.tsx +28 -28
  22. package/src/blog/swr.tsx +4 -7
  23. package/src/blog/utils/index.ts +9 -172
  24. package/vite.config.js +2 -1
  25. package/src/blog/articles/anti-logic.mdx +0 -61
  26. package/src/blog/articles/bbking-manual.mdx +0 -7
  27. package/src/blog/articles/black-river.mdx +0 -8
  28. package/src/blog/articles/celebration.mdx +0 -21
  29. package/src/blog/articles/cloth.mdx +0 -11
  30. package/src/blog/articles/cooking.mdx +0 -7
  31. package/src/blog/articles/cooldown.mdx +0 -12
  32. package/src/blog/articles/cousin.mdx +0 -15
  33. package/src/blog/articles/fall.mdx +0 -8
  34. package/src/blog/articles/img.mdx +0 -104
  35. package/src/blog/articles/leaves.mdx +0 -7
  36. package/src/blog/articles/liqiu.mdx +0 -7
  37. package/src/blog/articles/loading.mdx +0 -144
  38. package/src/blog/articles/love.mdx +0 -19
  39. package/src/blog/articles/major-cold.mdx +0 -14
  40. package/src/blog/articles/marshroom.mdx +0 -17
  41. package/src/blog/articles/men-without-women.mdx +0 -19
  42. package/src/blog/articles/moment.mdx +0 -9
  43. package/src/blog/articles/movie-day.mdx +0 -15
  44. package/src/blog/articles/photos.mdx +0 -13
  45. package/src/blog/articles/projects.mdx +0 -8
  46. package/src/blog/articles/pseudo-spring.mdx +0 -7
  47. package/src/blog/articles/quote.mdx +0 -26
  48. package/src/blog/articles/red-gun.mdx +0 -19
  49. package/src/blog/articles/rice-noodle.mdx +0 -21
  50. package/src/blog/articles/spring-cooldown.mdx +0 -8
  51. package/src/blog/articles/spring-rain.mdx +0 -10
  52. package/src/blog/articles/travel.mdx +0 -22
  53. package/src/blog/articles/warming-up.mdx +0 -10
  54. package/src/blog/articles/web-burnning.mdx +0 -10
  55. package/src/blog/articles/woke-up.mdx +0 -7
  56. package/src/blog/articles/xwy-and-snowing.mdx +0 -13
  57. package/src/blog/articles/xwy.mdx +0 -9
  58. package/src/blog/components/ImageUploader.tsx +0 -55
  59. package/src/blog/components/Img_ctx_menu/index.tsx +0 -67
  60. package/src/blog/components/Logger.tsx +0 -9
  61. package/src/blog/components/Pochacco/Pochacco.tsx +0 -29
  62. package/src/blog/components/Pochacco/idle.tsx +0 -31
  63. package/src/blog/components/Pochacco/watch.tsx +0 -28
  64. package/src/blog/components/Version.tsx +0 -14
  65. package/src/blog/components/app_ctx_menu/LoginMenuItem.tsx +0 -72
  66. package/src/blog/components/app_ctx_menu/PostMenuItem.tsx +0 -22
  67. package/src/blog/components/app_ctx_menu/VersionMenuItem.tsx +0 -13
  68. package/src/blog/components/app_ctx_menu/ViewSourceMenuItem.tsx +0 -34
  69. package/src/blog/components/app_ctx_menu/index.tsx +0 -35
  70. package/src/blog/components/article_ctx_menu/index.tsx +0 -58
  71. package/src/blog/components/blur_cover/index.tsx +0 -28
  72. package/src/blog/components/hotkey_nav/index.tsx +0 -51
  73. package/src/blog/components/progress_bar/index.tsx +0 -31
  74. package/src/blog/components/reaction/emojis.tsx +0 -143
  75. package/src/blog/components/reaction/oh_reaction.tsx +0 -105
  76. package/src/blog/components/reload_prompt/index.tsx +0 -51
  77. package/src/blog/components/tags/index.tsx +0 -52
  78. package/src/blog/hooks/useLoadingIndicator.ts +0 -12
  79. package/src/blog/hooks/useScrollToTop.ts +0 -24
  80. package/src/blog/hooks/useTransitionCls.ts +0 -36
  81. package/src/blog/hooks/use_authed.ts +0 -7
  82. package/src/blog/hooks/use_authed_fetcher.ts +0 -9
  83. package/src/blog/hooks/use_authed_string_post.ts +0 -42
  84. package/src/blog/hooks/use_clipboard_content.ts +0 -21
  85. package/src/blog/hooks/use_clipboard_to_post.ts +0 -48
  86. package/src/blog/hooks/use_del_img.ts +0 -22
  87. package/src/blog/hooks/use_delete_post.ts +0 -22
  88. package/src/blog/hooks/use_file_to_post.ts +0 -38
  89. package/src/blog/hooks/use_img_loading.ts +0 -16
  90. package/src/blog/hooks/use_post.ts +0 -26
  91. package/src/blog/hooks/use_projects.ts +0 -67
  92. package/src/blog/hooks/use_route_name.ts +0 -7
  93. package/src/blog/hooks/use_shared_string_to_post.ts +0 -23
  94. package/src/blog/hooks/use_supa_session.ts +0 -32
  95. package/src/blog/hooks/use_text_plain_file.ts +0 -36
  96. package/src/blog/hooks/use_uploader.ts +0 -34
  97. package/src/blog/hooks/use_video_controls.ts +0 -71
  98. package/src/blog/types/supabase.ts +0 -12
  99. package/src/blog/types/upload.ts +0 -16
  100. package/src/blog/utils/tags.ts +0 -21
@@ -1,28 +0,0 @@
1
- import React from "react";
2
- import { PochaccoProps } from "@/components/Pochacco/Pochacco";
3
-
4
- export const Watch = (props: PochaccoProps) => (
5
- <svg
6
- xmlns="http://www.w3.org/2000/svg"
7
- version="1.0"
8
- width={props.size || 48}
9
- height={props.size || 48}
10
- viewBox="0 0 128.000000 128.000000"
11
- preserveAspectRatio="xMidYMid meet"
12
- >
13
- <g
14
- transform="translate(0.000000,128.000000) scale(0.100000,-0.100000)"
15
- fill="#000000"
16
- stroke="none"
17
- >
18
- <path d="M1090 1111 c0 -39 -1 -41 -42 -52 -24 -7 -68 -11 -98 -9 -90 4 -105 3 -133 -4 -15 -3 -27 -12 -27 -20 0 -10 15 -12 68 -8 53 3 76 0 103 -13 47 -25 78 -50 106 -87 22 -31 23 -39 23 -210 l0 -178 -25 0 c-36 0 -99 -34 -151 -82 -39 -36 -50 -41 -108 -45 -62 -5 -66 -4 -95 25 -21 21 -31 40 -31 61 0 22 -5 31 -16 31 -14 0 -16 -8 -11 -45 8 -79 52 -108 155 -106 59 1 62 0 62 -23 0 -15 12 -35 32 -51 28 -24 38 -26 78 -21 25 3 57 15 72 26 15 11 29 20 32 20 3 0 7 -44 8 -97 4 -144 22 -122 31 37 8 158 8 141 -1 559 -5 245 -10 325 -19 329 -9 2 -13 -9 -13 -37z m-20 -101 c0 -5 -4 -10 -9 -10 -6 0 -13 5 -16 10 -3 6 1 10 9 10 9 0 16 -4 16 -10z m21 -520 c23 -13 25 -50 3 -96 -14 -28 -19 -32 -35 -24 -19 11 -69 78 -69 93 0 8 56 36 73 37 5 0 17 -5 28 -10z" />
19
- <path d="M760 1091 c-14 -27 -13 -51 3 -51 17 0 69 54 60 63 -13 14 -53 6 -63 -12z" />
20
- <path d="M647 1053 c-18 -17 -5 -33 28 -33 39 0 46 14 16 30 -23 12 -35 13 -44 3z" />
21
- <path d="M599 1000 c-5 -29 -2 -33 27 -35 46 -4 65 11 40 30 -22 17 -65 20 -67 5z" />
22
- <path d="M607 932 c-9 -10 -27 -42 -40 -72 -14 -30 -43 -77 -66 -105 -58 -70 -83 -126 -89 -201 -4 -57 -3 -64 13 -64 28 0 101 82 118 131 l15 44 20 -45 c27 -60 46 -85 60 -76 8 5 2 26 -19 69 -54 106 -49 238 11 292 23 21 26 45 7 45 -8 0 -21 -8 -30 -18z m-117 -261 c0 -12 -20 -25 -27 -18 -7 7 6 27 18 27 5 0 9 -4 9 -9z m30 -11 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m-60 -59 c0 -6 -4 -13 -10 -16 -5 -3 -10 1 -10 9 0 9 5 16 10 16 6 0 10 -4 10 -9z" />
23
- <path d="M1020 726 c0 -28 12 -46 30 -46 25 0 33 16 20 40 -12 23 -50 27 -50 6z" />
24
- <path d="M920 615 c-28 -33 13 -61 44 -29 20 20 20 30 0 38 -23 9 -30 8 -44 -9z" />
25
- <path d="M770 586 c0 -26 24 -51 40 -41 14 8 13 38 -2 53 -19 19 -38 14 -38 -12z" />
26
- </g>
27
- </svg>
28
- );
@@ -1,14 +0,0 @@
1
- import { Tag } from "@bbki.ng/components";
2
- import React from "react";
3
-
4
- export const Version = ({ className }: { className?: string }) => {
5
- // @ts-ignore
6
- const appVer = GLOBAL_BBKING_VERSION;
7
- const tagUrl = `https://github.com/bbbottle/bottle/releases/tag/@bbki.ng/site@${appVer}`;
8
-
9
- return (
10
- <Tag to={tagUrl} external prefix="v" className={className}>
11
- {appVer}
12
- </Tag>
13
- );
14
- };
@@ -1,72 +0,0 @@
1
- import { useAuthed } from "@/hooks/use_authed";
2
- import { useSupabaseSession } from "@/hooks/use_supa_session";
3
- import {
4
- ContextMenuItem,
5
- ContextMenuLabel,
6
- ContextMenuShortcut,
7
- Link,
8
- } from "@bbki.ng/components";
9
- import React from "react";
10
- import { useNavigate } from "react-router-dom";
11
- import { supabase } from "@/constants";
12
- import { toast } from "sonner";
13
- import { confirm } from "@/utils";
14
-
15
- export const LoginMenuItem = () => {
16
- const sess = useSupabaseSession();
17
- const nav = useNavigate();
18
-
19
- if (sess?.user != null) {
20
- return (
21
- <ContextMenuItem
22
- onClick={() => {
23
- confirm("确定退出登录吗?", () => {
24
- supabase.auth.signOut().then(() => {
25
- toast.success("已退出登录", {
26
- position: "bottom-right",
27
- });
28
- });
29
- });
30
- }}
31
- >
32
- {sess?.user?.user_metadata && (
33
- <img
34
- src={sess?.user?.user_metadata.avatar_url}
35
- alt="avatar"
36
- style={{ width: 16, height: 16 }}
37
- className="mr-8"
38
- crossOrigin="anonymous"
39
- />
40
- )}
41
- {sess?.user?.email ?? ""}
42
- </ContextMenuItem>
43
- );
44
- }
45
-
46
- return (
47
- <ContextMenuItem
48
- onClick={() => {
49
- nav("/login");
50
- }}
51
- >
52
- <svg
53
- xmlns="http://www.w3.org/2000/svg"
54
- width="16"
55
- height="16"
56
- viewBox="0 0 24 24"
57
- fill="none"
58
- stroke="currentColor"
59
- strokeWidth="2"
60
- strokeLinecap="round"
61
- strokeLinejoin="round"
62
- className="feather feather-log-in mr-8"
63
- >
64
- <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
65
- <polyline points="10 17 15 12 10 7"></polyline>
66
- <line x1="15" y1="12" x2="3" y2="12"></line>
67
- </svg>
68
- login
69
- <ContextMenuShortcut className="mr-1">l</ContextMenuShortcut>
70
- </ContextMenuItem>
71
- );
72
- };
@@ -1,22 +0,0 @@
1
- import { ContextMenuItem } from "@bbki.ng/components";
2
- import React from "react";
3
- import {useAuthedStringPost} from "@/hooks/use_authed_string_post";
4
-
5
- export const PostMenuItem = () => {
6
-
7
- const post = useAuthedStringPost();
8
-
9
- const postFromClipboard = () => {
10
- navigator.clipboard
11
- .readText()
12
- .then(post);
13
- }
14
-
15
- return (
16
- <ContextMenuItem onClick={postFromClipboard}
17
- inset
18
- >
19
- post from clipboard
20
- </ContextMenuItem>
21
- );
22
- };
@@ -1,13 +0,0 @@
1
- import { ContextMenuItem, Tag } from "@bbki.ng/components";
2
- import React from "react";
3
-
4
- export const VersionMenuItem = () => {
5
- // @ts-ignore
6
- const appVer = GLOBAL_BBKING_VERSION;
7
-
8
- return (
9
- <ContextMenuItem inset disabled>
10
- v{appVer}
11
- </ContextMenuItem>
12
- );
13
- };
@@ -1,34 +0,0 @@
1
- import { ContextMenuItem, ContextMenuShortcut } from "@bbki.ng/components";
2
- import React from "react";
3
- import { GITHUB_REPO_ADDRESS } from "@/constants";
4
-
5
- export const ViewSourceMenuItem = () => {
6
- // @ts-ignore
7
- const appVer = GLOBAL_BBKING_VERSION;
8
- return (
9
- <ContextMenuItem
10
- onClick={() => {
11
- // open tagUrl in new tab
12
- window.open(GITHUB_REPO_ADDRESS, "_blank");
13
- }}
14
- >
15
- <svg
16
- xmlns="http://www.w3.org/2000/svg"
17
- width="16"
18
- height="16"
19
- viewBox="0 0 24 24"
20
- fill="none"
21
- stroke="currentColor"
22
- strokeWidth="2"
23
- strokeLinecap="round"
24
- strokeLinejoin="round"
25
- className="feather feather-code mr-8"
26
- >
27
- <polyline points="16 18 22 12 16 6"></polyline>
28
- <polyline points="8 6 2 12 8 18"></polyline>
29
- </svg>
30
- v{appVer}
31
- <ContextMenuShortcut className="mr-1">s</ContextMenuShortcut>
32
- </ContextMenuItem>
33
- );
34
- };
@@ -1,35 +0,0 @@
1
- import React, { ReactElement, useEffect } from "react";
2
- import {
3
- ContextMenu,
4
- ContextMenuContent,
5
- ContextMenuTrigger,
6
- ContextMenuSeparator,
7
- ContextMenuShortcut,
8
- ContextMenuItem,
9
- } from "@bbki.ng/components";
10
- import { LoginMenuItem } from "@/components/app_ctx_menu/LoginMenuItem";
11
- import { ViewSourceMenuItem } from "@/components/app_ctx_menu/ViewSourceMenuItem";
12
- import { PostMenuItem } from "@/components/app_ctx_menu/PostMenuItem";
13
- import { useAuthed } from "@/hooks/use_authed";
14
-
15
- export const AppCtxMenu = (props: { children: ReactElement }) => {
16
- const [showPluginEntry, setShowPluginEntry] = React.useState(false);
17
-
18
- const showEntry = () => {
19
- setShowPluginEntry(true);
20
- };
21
-
22
- const isKing = useAuthed();
23
-
24
- return (
25
- <ContextMenu>
26
- <ContextMenuTrigger>{props.children}</ContextMenuTrigger>
27
- <ContextMenuContent className="">
28
- <LoginMenuItem />
29
- <ViewSourceMenuItem />
30
- {isKing && <PostMenuItem />}
31
- {/*{showPluginEntry && <PluginsMenuItem />}*/}
32
- </ContextMenuContent>
33
- </ContextMenu>
34
- );
35
- };
@@ -1,58 +0,0 @@
1
- import React, { ReactElement, useCallback } from "react";
2
- import { useAuthed } from "@/hooks/use_authed";
3
- import {
4
- ContextMenu,
5
- ContextMenuContent,
6
- ContextMenuTrigger,
7
- ContextMenuItem,
8
- } from "@bbki.ng/components";
9
- import { useNavigate, useParams } from "react-router-dom";
10
- import { useDelPost } from "@/hooks/use_delete_post";
11
- import { toast } from "sonner";
12
- import { confirm } from "@/utils";
13
- import { useLoadingIndicator } from "@/hooks/useLoadingIndicator";
14
-
15
- export const ArticleCtxMenu = (props: { children: ReactElement }) => {
16
- const auth = useAuthed();
17
- const del = useDelPost();
18
- const routeParams = useParams();
19
- const nav = useNavigate();
20
- const title = routeParams.title;
21
- const dot = useLoadingIndicator();
22
-
23
- if (!auth) {
24
- return props.children;
25
- }
26
-
27
- if (title == null || title === "") {
28
- return props.children;
29
- }
30
-
31
- const doDel = useCallback(() => {
32
- dot.setVisibility(true);
33
- del(title)
34
- .then(() => {
35
- toast.success("删除成功", {
36
- position: "bottom-right",
37
- });
38
- dot.setVisibility(false);
39
- nav("/blog");
40
- })
41
- .catch(console.log);
42
- }, [title]);
43
-
44
- return (
45
- <ContextMenu>
46
- <ContextMenuTrigger>{props.children}</ContextMenuTrigger>
47
- <ContextMenuContent>
48
- <ContextMenuItem
49
- onClick={() => {
50
- confirm("确认删除?", doDel);
51
- }}
52
- >
53
- remove
54
- </ContextMenuItem>
55
- </ContextMenuContent>
56
- </ContextMenu>
57
- );
58
- };
@@ -1,28 +0,0 @@
1
- import React from "react";
2
- import classnames from "classnames";
3
- import { TextColors } from "@/types/color";
4
-
5
- type blurCoverProps = {
6
- textColor?: TextColors;
7
- className?: string;
8
- children: any;
9
- height?: number;
10
- visibleOnHover?: boolean;
11
- };
12
-
13
- export const BlurCover = (props: blurCoverProps) => {
14
- const { textColor, children, className, height = 50, visibleOnHover } = props;
15
- const cls = classnames(
16
- className,
17
- textColor,
18
- "blur-cover",
19
- "absolute",
20
- "w-full",
21
- "flex items-center justify-center"
22
- );
23
- return (
24
- <div className={cls} style={{ height }}>
25
- {children}
26
- </div>
27
- );
28
- };
@@ -1,51 +0,0 @@
1
- import { useNavigate } from "react-router-dom";
2
- import { useHotkeys } from "react-hotkeys-hook";
3
- import { GITHUB_REPO_ADDRESS, ROUTES } from "@/constants";
4
-
5
- enum HotKeys {
6
- i = "i",
7
- e = "e",
8
- c = "c",
9
- t = "t",
10
- p = "p",
11
- a = "a",
12
- f = "f",
13
- b = "b",
14
- h = "h",
15
- s = "s",
16
- l = "l",
17
- T = "shift+t",
18
- }
19
-
20
- const KEY_ROUTES = [
21
- { key: HotKeys.i, route: ROUTES.INDEX },
22
- { key: HotKeys.c, route: ROUTES.CONTENT },
23
- { key: HotKeys.h, route: ROUTES.HELP },
24
- { key: HotKeys.t, route: ROUTES.TAGS },
25
- { key: HotKeys.l, route: ROUTES.LOGIN },
26
- ];
27
-
28
- export const HotKeyNav = (props: any) => {
29
- const nav = useNavigate();
30
- const goto = (path: string) => {
31
- nav(path);
32
- };
33
-
34
- useHotkeys(HotKeys.b, () => {
35
- nav(-1);
36
- });
37
- useHotkeys(HotKeys.f, () => {
38
- nav(1);
39
- });
40
- useHotkeys(HotKeys.s, () => {
41
- window.open(GITHUB_REPO_ADDRESS);
42
- });
43
-
44
- KEY_ROUTES.map(({ key, route }) => {
45
- useHotkeys(key, () => {
46
- goto(route);
47
- });
48
- });
49
-
50
- return props.children;
51
- };
@@ -1,31 +0,0 @@
1
- import React from "react";
2
- import classnames from "classnames";
3
- import { BgColors } from "@/types/color";
4
- import { floatNumberToPercentageString } from "@/utils";
5
-
6
- type progressBarProps = {
7
- bgColor?: BgColors;
8
- fgColor?: BgColors;
9
- height?: number;
10
- progress: number;
11
- };
12
-
13
- export const ProgressBar = (props: progressBarProps) => {
14
- const {
15
- height = 2,
16
- fgColor = BgColors.BLUE,
17
- bgColor = BgColors.GRAY,
18
- progress,
19
- } = props;
20
-
21
- const wrapperCls = classnames("w-full", "text-left", bgColor);
22
- const innerBarCls = classnames("h-full", fgColor);
23
- return (
24
- <div className={wrapperCls} style={{ height }}>
25
- <div
26
- className={innerBarCls}
27
- style={{ width: floatNumberToPercentageString(progress) }}
28
- />
29
- </div>
30
- );
31
- };
@@ -1,143 +0,0 @@
1
- import React from "react";
2
- import { ReactNode } from "react";
3
-
4
- const HEART_SIZE = 12;
5
-
6
- export interface ReactionEmojiPair {
7
- on: ReactNode;
8
- off: ReactNode;
9
- val: string;
10
- }
11
-
12
- const heart = (
13
- <svg
14
- data-testid="geist-icon"
15
- height={HEART_SIZE}
16
- width={HEART_SIZE}
17
- stroke-linejoin="round"
18
- viewBox="0 0 16 16"
19
- >
20
- <path
21
- fill-rule="evenodd"
22
- clip-rule="evenodd"
23
- 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"
24
- fill="currentColor"
25
- ></path>
26
- </svg>
27
- );
28
-
29
- const heartFill = (
30
- <svg
31
- data-testid="geist-icon"
32
- height={HEART_SIZE}
33
- width={HEART_SIZE}
34
- stroke-linejoin="round"
35
- className="text-red-400"
36
- viewBox={`0 0 16 16`}
37
- >
38
- <path
39
- 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"
40
- fill="currentColor"
41
- ></path>
42
- </svg>
43
- );
44
-
45
- const happyFace = (
46
- <svg
47
- data-testid="geist-icon"
48
- stroke-linejoin="round"
49
- height={HEART_SIZE}
50
- width={HEART_SIZE}
51
- viewBox="0 0 16 16"
52
- >
53
- <path
54
- fill-rule="evenodd"
55
- clip-rule="evenodd"
56
- d="M14.5 8C14.5 11.5899 11.5899 14.5 8 14.5C4.41015 14.5 1.5 11.5899 1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8ZM16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM11.5249 10.8478L11.8727 10.3286L10.8342 9.6329L10.4863 10.1522C9.94904 10.9543 9.0363 11.4802 8.00098 11.4802C6.96759 11.4802 6.05634 10.9563 5.51863 10.1567L5.16986 9.63804L4.13259 10.3356L4.48137 10.8542C5.2414 11.9844 6.53398 12.7302 8.00098 12.7302C9.47073 12.7302 10.7654 11.9816 11.5249 10.8478ZM6.75 6.75C6.75 7.30228 6.30228 7.75 5.75 7.75C5.19772 7.75 4.75 7.30228 4.75 6.75C4.75 6.19772 5.19772 5.75 5.75 5.75C6.30228 5.75 6.75 6.19772 6.75 6.75ZM10.25 7.75C10.8023 7.75 11.25 7.30228 11.25 6.75C11.25 6.19772 10.8023 5.75 10.25 5.75C9.69771 5.75 9.25 6.19772 9.25 6.75C9.25 7.30228 9.69771 7.75 10.25 7.75Z"
57
- fill="currentColor"
58
- ></path>
59
- </svg>
60
- );
61
-
62
- const smileFace = (
63
- <svg
64
- height={HEART_SIZE}
65
- width={HEART_SIZE}
66
- data-testid="geist-icon"
67
- className="text-gray-400"
68
- stroke-linejoin="round"
69
- viewBox="0 0 16 16"
70
- >
71
- <path
72
- fill-rule="evenodd"
73
- clip-rule="evenodd"
74
- d="M14.5 8C14.5 11.5899 11.5899 14.5 8 14.5C4.41015 14.5 1.5 11.5899 1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8ZM16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM4.5 8.97498H3.875V9.59998C3.875 11.4747 5.81046 12.8637 7.99817 12.8637C10.1879 12.8637 12.125 11.4832 12.125 9.59998V8.97498H11.5H4.5ZM7.99817 11.6137C6.59406 11.6137 5.63842 10.9482 5.28118 10.225H10.7202C10.3641 10.9504 9.40797 11.6137 7.99817 11.6137Z"
75
- fill="currentColor"
76
- ></path>
77
- <path
78
- fill-rule="evenodd"
79
- clip-rule="evenodd"
80
- d="M6.15295 4.92093L5.375 3.5L4.59705 4.92093L3 5.21885L4.11625 6.39495L3.90717 8L5.375 7.30593L6.84283 8L6.63375 6.39495L7.75 5.21885L6.15295 4.92093ZM11.403 4.92093L10.625 3.5L9.84705 4.92093L8.25 5.21885L9.36625 6.39495L9.15717 8L10.625 7.30593L12.0928 8L11.8837 6.39495L13 5.21885L11.403 4.92093Z"
81
- fill="var(--ds-amber-800)"
82
- ></path>
83
- </svg>
84
- );
85
-
86
- const unhappyFace = (
87
- <svg
88
- data-testid="geist-icon"
89
- stroke-linejoin="round"
90
- viewBox="0 0 16 16"
91
- height={HEART_SIZE}
92
- width={HEART_SIZE}
93
- >
94
- <path
95
- fill-rule="evenodd"
96
- clip-rule="evenodd"
97
- d="M14.5 8C14.5 11.5899 11.5899 14.5 8 14.5C4.41015 14.5 1.5 11.5899 1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8ZM16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM5.75 7.75C6.30228 7.75 6.75 7.30228 6.75 6.75C6.75 6.19772 6.30228 5.75 5.75 5.75C5.19772 5.75 4.75 6.19772 4.75 6.75C4.75 7.30228 5.19772 7.75 5.75 7.75ZM11.25 6.75C11.25 7.30228 10.8023 7.75 10.25 7.75C9.69771 7.75 9.25 7.30228 9.25 6.75C9.25 6.19772 9.69771 5.75 10.25 5.75C10.8023 5.75 11.25 6.19772 11.25 6.75ZM11.5249 11.2622L11.8727 11.7814L10.8342 12.4771L10.4863 11.9578C9.94904 11.1557 9.0363 10.6298 8.00098 10.6298C6.96759 10.6298 6.05634 11.1537 5.51863 11.9533L5.16986 12.4719L4.13259 11.7744L4.48137 11.2558C5.2414 10.1256 6.53398 9.37982 8.00098 9.37982C9.47073 9.37982 10.7654 10.1284 11.5249 11.2622Z"
98
- fill="currentColor"
99
- ></path>
100
- </svg>
101
- );
102
-
103
- const sadFace = (
104
- <svg
105
- data-testid="geist-icon"
106
- stroke-linejoin="round"
107
- height={HEART_SIZE}
108
- width={HEART_SIZE}
109
- viewBox="0 0 16 16"
110
- className="text-gray-400"
111
- >
112
- <path
113
- fill-rule="evenodd"
114
- clip-rule="evenodd"
115
- d="M4 9V16H5.5V9H4ZM12 9V16H10.5V9H12Z"
116
- fill="var(--ds-blue-700)"
117
- ></path>
118
- <path
119
- fill-rule="evenodd"
120
- clip-rule="evenodd"
121
- d="M1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8C14.5 9.57941 13.9367 11.0273 13 12.1536V14.2454C14.8289 12.7793 16 10.5264 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8C0 10.5264 1.17107 12.7793 3 14.2454V12.1536C2.06332 11.0273 1.5 9.57941 1.5 8ZM8 14.5C8.51627 14.5 9.01848 14.4398 9.5 14.3261V15.8596C9.01412 15.9518 8.51269 16 8 16C7.48731 16 6.98588 15.9518 6.5 15.8596V14.3261C6.98152 14.4398 7.48373 14.5 8 14.5ZM3.78568 8.36533C4.15863 7.98474 4.67623 7.75 5.25 7.75C5.82377 7.75 6.34137 7.98474 6.71432 8.36533L7.78568 7.31548C7.14222 6.65884 6.24318 6.25 5.25 6.25C4.25682 6.25 3.35778 6.65884 2.71432 7.31548L3.78568 8.36533ZM10.75 7.75C10.1762 7.75 9.65863 7.98474 9.28568 8.36533L8.21432 7.31548C8.85778 6.65884 9.75682 6.25 10.75 6.25C11.7432 6.25 12.6422 6.65884 13.2857 7.31548L12.2143 8.36533C11.8414 7.98474 11.3238 7.75 10.75 7.75ZM6.25 12H9.75C9.75 11.0335 8.9665 10.25 8 10.25C7.0335 10.25 6.25 11.0335 6.25 12Z"
122
- fill="currentColor"
123
- ></path>
124
- </svg>
125
- );
126
-
127
- export const hearts: ReactionEmojiPair = {
128
- on: heartFill,
129
- off: heart,
130
- val: "❤️",
131
- };
132
-
133
- export const faces: ReactionEmojiPair = {
134
- on: smileFace,
135
- off: happyFace,
136
- val: "🙂",
137
- };
138
-
139
- export const sadFaces: ReactionEmojiPair = {
140
- on: sadFace,
141
- off: unhappyFace,
142
- val: "😞",
143
- };
@@ -1,105 +0,0 @@
1
- import React, {
2
- ReactNode,
3
- useContext,
4
- useEffect,
5
- useRef,
6
- useState,
7
- } from "react";
8
- import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
9
- import { BlinkDot, Button, ButtonType } from "@bbki.ng/components";
10
- import { faces, hearts, ReactionEmojiPair, sadFaces } from "./emojis";
11
- import { ShareBtn } from "../share/share-btn";
12
-
13
- declare global {
14
- namespace JSX {
15
- interface IntrinsicElements {
16
- "open-heart": React.DetailedHTMLProps<
17
- React.HTMLAttributes<HTMLElement> & {
18
- href?: string;
19
- emoji?: string;
20
- ariaDisabled?: boolean;
21
- onClick?: React.MouseEventHandler<HTMLElement>;
22
- },
23
- HTMLElement
24
- >;
25
- }
26
- }
27
- }
28
-
29
- const useHeartSent = (val: string) => {
30
- const [sent, setSent] = useState(false);
31
- const { setIsLoading } = useContext(GlobalLoadingContext);
32
-
33
- const handleSent = (evt: Event) => {
34
- const targetVal = (evt.target as HTMLElement).getAttribute("emoji");
35
-
36
- if (targetVal == val) setSent(true);
37
- setIsLoading(false);
38
- };
39
-
40
- useEffect(() => {
41
- addEventListener("open-heart", handleSent);
42
-
43
- return () => {
44
- removeEventListener("open-heart", handleSent);
45
- };
46
- }, []);
47
-
48
- return sent;
49
- };
50
-
51
- export const OpenHeartReaction = (props: {
52
- title: string;
53
- emojiPair: ReactionEmojiPair;
54
- }) => {
55
- const { title, emojiPair = hearts } = props;
56
- const sent = useHeartSent(emojiPair.val);
57
-
58
- const { setIsLoading } = useContext(GlobalLoadingContext);
59
-
60
- const ohRef = useRef<HTMLElement>(null);
61
-
62
- const pressed = () => ohRef.current?.getAttribute("aria-pressed");
63
-
64
- const handleHeartClick = () => {
65
- if (sent || pressed()) {
66
- return;
67
- }
68
-
69
- setIsLoading(true);
70
- };
71
-
72
- return (
73
- <open-heart
74
- ref={ohRef}
75
- href={`https://oh.bbki.ng/?id=${title}`}
76
- emoji={emojiPair.val}
77
- >
78
- <Button
79
- size="small"
80
- type={ButtonType.GHOST}
81
- className="text-gray-400 hover:text-gray-600 transition-colors ease-in duration-200"
82
- onClick={handleHeartClick}
83
- >
84
- {sent || pressed() ? emojiPair.on : emojiPair.off}
85
- </Button>
86
- </open-heart>
87
- );
88
- };
89
-
90
- export const Reaction = (props: { title: string; url: string }) => {
91
- return (
92
- <div className="flex items-center">
93
- <OpenHeartReaction title={props.title} emojiPair={hearts} />
94
- <OpenHeartReaction title={props.title} emojiPair={faces} />
95
- <OpenHeartReaction title={props.title} emojiPair={sadFaces} />
96
-
97
- <ShareBtn
98
- shareInfo={{
99
- title: props.title,
100
- url: props.url,
101
- }}
102
- />
103
- </div>
104
- );
105
- };