@bbki.ng/site 0.0.17

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 (117) hide show
  1. package/.github/workflows/deploy.yml +44 -0
  2. package/.husky/pre-commit +4 -0
  3. package/.prettierignore +1 -0
  4. package/.prettierrc.json +1 -0
  5. package/.rush/temp/shrinkwrap-deps.json +908 -0
  6. package/CODE_OF_CONDUCT.md +45 -0
  7. package/CONTRIBUTING.md +11 -0
  8. package/LICENSE +21 -0
  9. package/README.md +21 -0
  10. package/index.html +33 -0
  11. package/jest.config.js +15 -0
  12. package/package.json +69 -0
  13. package/postcss.config.cjs +6 -0
  14. package/public/Logo.svg +9 -0
  15. package/public/apple-touch-icon.png +0 -0
  16. package/public/favicon-16x16.png +0 -0
  17. package/public/favicon-32x32.png +0 -0
  18. package/public/favicon.ico +0 -0
  19. package/public/favicon.svg +9 -0
  20. package/public/pwa-192x192.png +0 -0
  21. package/public/pwa-512x512.png +0 -0
  22. package/public/robots.txt +2 -0
  23. package/src/__test__/utils/index.test.ts +90 -0
  24. package/src/app.tsx +97 -0
  25. package/src/articles/anti-logic.mdx +61 -0
  26. package/src/articles/bbking-manual.mdx +88 -0
  27. package/src/articles/black-river.mdx +8 -0
  28. package/src/articles/cooldown.mdx +12 -0
  29. package/src/articles/fall.mdx +8 -0
  30. package/src/articles/img.mdx +104 -0
  31. package/src/articles/index.ts +35 -0
  32. package/src/articles/loading.mdx +129 -0
  33. package/src/articles/major-cold.mdx +14 -0
  34. package/src/articles/men-without-women.mdx +19 -0
  35. package/src/articles/movie-day.mdx +15 -0
  36. package/src/articles/now.mdx +15 -0
  37. package/src/articles/projects.mdx +9 -0
  38. package/src/articles/quote.mdx +27 -0
  39. package/src/articles/spring-cooldown.mdx +7 -0
  40. package/src/articles/spring-rain.mdx +9 -0
  41. package/src/articles/travel.mdx +21 -0
  42. package/src/articles/warming-up.mdx +10 -0
  43. package/src/articles/web-burnning.mdx +10 -0
  44. package/src/auth_required.tsx +17 -0
  45. package/src/components/Spinner.tsx +33 -0
  46. package/src/components/article/index.tsx +31 -0
  47. package/src/components/aspect_ratio_box/index.tsx +29 -0
  48. package/src/components/blur_cover/index.tsx +28 -0
  49. package/src/components/book_list/index.tsx +50 -0
  50. package/src/components/comment/index.tsx +70 -0
  51. package/src/components/comment/use_cusdis_event.ts +37 -0
  52. package/src/components/corner_prompt_box/index.tsx +63 -0
  53. package/src/components/disabled_text/index.tsx +23 -0
  54. package/src/components/fade_out_cover/index.tsx +37 -0
  55. package/src/components/footer/footer_links.ts +13 -0
  56. package/src/components/footer/index.tsx +21 -0
  57. package/src/components/hotkey_nav/index.tsx +50 -0
  58. package/src/components/img_list/index.tsx +43 -0
  59. package/src/components/index.tsx +27 -0
  60. package/src/components/movie_list/index.tsx +50 -0
  61. package/src/components/my_suspense.tsx +14 -0
  62. package/src/components/progress_bar/index.tsx +31 -0
  63. package/src/components/reload_prompt/index.tsx +36 -0
  64. package/src/components/stickers/index.tsx +46 -0
  65. package/src/components/table_skeleton/index.tsx +40 -0
  66. package/src/components/tags/index.tsx +52 -0
  67. package/src/components/video_player/index.tsx +81 -0
  68. package/src/components/with_wrapper/index.tsx +13 -0
  69. package/src/constants/cusdis.ts +6 -0
  70. package/src/constants/index.ts +16 -0
  71. package/src/constants/photo_projects.ts +54 -0
  72. package/src/constants/photos.ts +270 -0
  73. package/src/constants/routes.ts +24 -0
  74. package/src/constants/video_logs.ts +16 -0
  75. package/src/demo/DemoBox.tsx +15 -0
  76. package/src/demo/ImgDemo.tsx +34 -0
  77. package/src/demo/SpinnerDemo.tsx +17 -0
  78. package/src/global/mdx.d.ts +8 -0
  79. package/src/global_loading_state_provider.tsx +27 -0
  80. package/src/hooks/index.ts +15 -0
  81. package/src/hooks/useScrollToTop.ts +24 -0
  82. package/src/hooks/useTransitionCls.ts +36 -0
  83. package/src/hooks/use_img_loading.ts +16 -0
  84. package/src/hooks/use_pathname.ts +6 -0
  85. package/src/hooks/use_paths.ts +30 -0
  86. package/src/hooks/use_projects.ts +56 -0
  87. package/src/hooks/use_route_name.ts +7 -0
  88. package/src/hooks/use_supa_session.ts +30 -0
  89. package/src/hooks/use_uploader.ts +34 -0
  90. package/src/hooks/use_video_controls.ts +71 -0
  91. package/src/main.css +156 -0
  92. package/src/main.tsx +19 -0
  93. package/src/pages/cover/index.tsx +10 -0
  94. package/src/pages/extensions/png/consts.ts +9 -0
  95. package/src/pages/extensions/png/index.tsx +41 -0
  96. package/src/pages/extensions/png/png_projects.tsx +63 -0
  97. package/src/pages/extensions/txt/article.tsx +26 -0
  98. package/src/pages/extensions/txt/consts.ts +8 -0
  99. package/src/pages/extensions/txt/index.tsx +21 -0
  100. package/src/pages/index.tsx +14 -0
  101. package/src/pages/login/index.tsx +33 -0
  102. package/src/pages/now/index.tsx +7 -0
  103. package/src/pages/tags/index.tsx +28 -0
  104. package/src/pages/tags/tag_result.tsx +19 -0
  105. package/src/swr.tsx +18 -0
  106. package/src/types/articles.ts +6 -0
  107. package/src/types/color.ts +21 -0
  108. package/src/types/cusdis.ts +4 -0
  109. package/src/types/oss.ts +15 -0
  110. package/src/types/path.ts +11 -0
  111. package/src/types/photo.ts +17 -0
  112. package/src/types/supabase.ts +9 -0
  113. package/src/utils/index.ts +143 -0
  114. package/src/utils/tags.ts +21 -0
  115. package/tailwind.config.cjs +10 -0
  116. package/tsconfig.json +24 -0
  117. package/vite.config.ts +108 -0
@@ -0,0 +1,81 @@
1
+ import React, { ReactEventHandler, useEffect, useState } from "react";
2
+ import classnames from "classnames";
3
+ import { useVideoControls, useVideoEleHeight, useVideoProgress } from "@/hooks";
4
+ import { BlurCover, ProgressBar } from "@/components";
5
+ import { BgColors, TextColors } from "@/types/color";
6
+ import { AspectRatioBox } from "@/components/aspect_ratio_box";
7
+ import { VIDEO_TAG_ASPECT_RATIO } from "@/constants";
8
+
9
+ type videoPlayProps = {
10
+ src: string;
11
+ className?: string;
12
+ };
13
+
14
+ export const VideoPlayer = (props: videoPlayProps) => {
15
+ const { src, className } = props;
16
+ const [hovered, setHovered] = useState(false);
17
+ const [showPlayer, setShowPlayer] = useState(false);
18
+ const { videoRef, toggle, isPlay } = useVideoControls();
19
+ const { progress, onTimeUpdate } = useVideoProgress();
20
+ const VideoHeight = useVideoEleHeight(videoRef);
21
+
22
+ useEffect(() => {
23
+ if (!videoRef.current) {
24
+ return;
25
+ }
26
+ videoRef.current.load();
27
+ }, []);
28
+
29
+ const onPlayerReady: ReactEventHandler = () => {
30
+ setShowPlayer(true);
31
+ };
32
+
33
+ const cls = classnames({ hidden: !showPlayer });
34
+
35
+ return (
36
+ <div
37
+ className={classnames(
38
+ "flex flex-col relative cursor-pointer",
39
+ className,
40
+ BgColors.LIGHT_GRAY
41
+ )}
42
+ onClick={async () => {
43
+ await toggle();
44
+ if (!isPlay) {
45
+ setHovered(false);
46
+ }
47
+ }}
48
+ onMouseEnter={() => {
49
+ setHovered(true);
50
+ }}
51
+ onMouseLeave={() => {
52
+ setHovered(false);
53
+ }}
54
+ >
55
+ <AspectRatioBox
56
+ width="100%"
57
+ hwRatio={VIDEO_TAG_ASPECT_RATIO}
58
+ className={BgColors.LIGHT_GRAY}
59
+ >
60
+ <video
61
+ playsInline
62
+ ref={videoRef}
63
+ src={src}
64
+ className={cls}
65
+ onTimeUpdate={onTimeUpdate}
66
+ onCanPlayThrough={onPlayerReady}
67
+ />
68
+ </AspectRatioBox>
69
+ {hovered && showPlayer && (
70
+ <BlurCover
71
+ textColor={isPlay ? TextColors.RED : TextColors.BLUE}
72
+ height={VideoHeight}
73
+ visibleOnHover
74
+ >
75
+ {isPlay ? "pause" : "play"}
76
+ </BlurCover>
77
+ )}
78
+ {showPlayer && <ProgressBar progress={progress} />}
79
+ </div>
80
+ );
81
+ };
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import { FunctionComponent } from "react";
3
+ import { ArticlePage } from "@/components/article";
4
+
5
+ export const withArticleWrapper =
6
+ (Component: FunctionComponent<any>): FunctionComponent<any> =>
7
+ (props: any) => {
8
+ return (
9
+ <ArticlePage {...props}>
10
+ <Component />
11
+ </ArticlePage>
12
+ );
13
+ };
@@ -0,0 +1,6 @@
1
+ export const CUSDIS_ATTRS = {
2
+ host: "https://bbcusdis.vercel.app",
3
+ appId: "f607ddca-f13d-4a91-8203-227f062f125f",
4
+ };
5
+
6
+ export const CUSDIS_OFFICIAL_SITE_ADDRESS = "https://cusdis.com/";
@@ -0,0 +1,16 @@
1
+ import { createClient } from "@supabase/supabase-js";
2
+
3
+ export { PHOTO_PROJECTS } from "./photo_projects";
4
+ export { VIDEO_LOGS, VIDEO_TAG_ASPECT_RATIO } from "./video_logs";
5
+ export { ROUTES, ROUTE_NAME, GITHUB_REPO_ADDRESS } from "./routes";
6
+ export const DEFAULT_DELAY = 200;
7
+ export const SUPABASE: {
8
+ ANNO: string;
9
+ URL: string;
10
+ BB_KING_ID: string;
11
+ } = {
12
+ ANNO: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImN2eHFtdXNmYXh3dXl2eXV1ZWNvIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NDQ4MjkwNTEsImV4cCI6MTk2MDQwNTA1MX0.lg90OVR7s6tjbDamVaI9FR2M2fc6OVfsfGd4j9MXu3M",
13
+ URL: "https://cvxqmusfaxwuyvyuueco.supabase.co",
14
+ BB_KING_ID: "e6795b1d-7ee0-4afe-be63-796670848175",
15
+ };
16
+ export const supabase = createClient(SUPABASE.URL, SUPABASE.ANNO);
@@ -0,0 +1,54 @@
1
+ import { OSS_PHOTOS } from "@/constants/photos";
2
+ import { PhotoProject } from "@/types/photo";
3
+
4
+ export const PHOTO_PROJECTS: PhotoProject[] = [
5
+ {
6
+ name: "过去的来意",
7
+ description: '"往事越千年"',
8
+ images: [OSS_PHOTOS.quyuan, OSS_PHOTOS.weapons, OSS_PHOTOS.stone],
9
+ },
10
+ {
11
+ name: "敬县城",
12
+ description: '"早秋惊落叶,飘零似客心。翻飞未肯下,犹言忆故林。"',
13
+ images: [
14
+ OSS_PHOTOS.motorcycle,
15
+ OSS_PHOTOS.cycle,
16
+ OSS_PHOTOS.corner,
17
+ OSS_PHOTOS.streetGames,
18
+ OSS_PHOTOS.localDishes,
19
+ ],
20
+ },
21
+ {
22
+ name: "海底的家",
23
+ description:
24
+ '"河流用一生梳理 \\ 地球的表情 \\ 沿岸收集人類的喜怒哀樂 \\ 檔案堆滿了海底的家"',
25
+ images: [
26
+ OSS_PHOTOS.playWithWater,
27
+ OSS_PHOTOS.shopping,
28
+ OSS_PHOTOS.chess,
29
+ OSS_PHOTOS.player,
30
+ // OSS_PHOTOS.swimmer,
31
+ OSS_PHOTOS.players,
32
+ // OSS_PHOTOS.dragonRiver,
33
+ // OSS_PHOTOS.riverAndBoats,
34
+ OSS_PHOTOS.riverSide,
35
+ OSS_PHOTOS.quilt,
36
+ // OSS_PHOTOS.fishing,
37
+ OSS_PHOTOS.waterLine,
38
+ OSS_PHOTOS.bridge,
39
+ OSS_PHOTOS.building,
40
+ OSS_PHOTOS.smoking,
41
+ // OSS_PHOTOS.jzBridge,
42
+ ],
43
+ },
44
+ // {
45
+ // name: "光前",
46
+ // description: "城中村,个人深圳经历出入口。",
47
+ // images: [OSS_PHOTOS.oldMan, OSS_PHOTOS.oldWomen, OSS_PHOTOS.littleChild],
48
+ // },
49
+ // {
50
+ // name: "三百零一",
51
+ // description: "陋室光影",
52
+ // images: [OSS_PHOTOS.phone, OSS_PHOTOS.chair],
53
+ // },
54
+ ];
@@ -0,0 +1,270 @@
1
+ import { BgColors } from "@/types/color";
2
+ import { ossProcessType } from "@/types/oss";
3
+
4
+ export const OSS_PHOTOS = {
5
+ playWithWater: {
6
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/DSCF2203-1.jpg",
7
+ avgColor: BgColors.LIGHT_GRAY,
8
+ processType: ossProcessType.PROG,
9
+ width: 1879,
10
+ height: 1238,
11
+ },
12
+ shopping: {
13
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/shopping.jpg",
14
+ avgColor: BgColors.LIGHT_GRAY,
15
+ width: 1746,
16
+ height: 1746,
17
+ },
18
+ quyuan: {
19
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/from-the-past/quyuan.webp",
20
+ avgColor: BgColors.LIGHT_GRAY,
21
+ width: 4126,
22
+ height: 6262,
23
+ },
24
+ stone: {
25
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/from-the-past/stone.webp",
26
+ avgColor: BgColors.LIGHT_GRAY,
27
+ renderedWidth: 300,
28
+ width: 5536,
29
+ height: 4126,
30
+ },
31
+ weapons: {
32
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/from-the-past/weapon.webp",
33
+ avgColor: BgColors.LIGHT_GRAY,
34
+ width: 6155,
35
+ height: 4126,
36
+ },
37
+ roof: {
38
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/DSCF1807.RAF.jpg",
39
+ avgColor: BgColors.LIGHT_GRAY,
40
+ width: 6262,
41
+ height: 3278,
42
+ },
43
+ chess: {
44
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/checkmate.webp",
45
+ avgColor: BgColors.LIGHT_GRAY,
46
+ width: 6262,
47
+ height: 4126,
48
+ },
49
+ swimmer: {
50
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/swimmer.jpg",
51
+ avgColor: BgColors.LIGHT_GRAY,
52
+ width: 6081,
53
+ height: 4126,
54
+ },
55
+ player: {
56
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/player-min.webp",
57
+ width: 2692,
58
+ height: 3546,
59
+ avgColor: BgColors.LIGHT_GRAY,
60
+ },
61
+ players: {
62
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/players.jpg",
63
+ width: 3368,
64
+ height: 2344,
65
+ avgColor: BgColors.LIGHT_GRAY,
66
+ },
67
+ fishing: {
68
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/p2705047873.webp",
69
+ thumbnailSrc:
70
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/p2705047873.webp?x-oss-process=style/thumbnail",
71
+ width: 1080,
72
+ height: 720,
73
+ avgColor: BgColors.LIGHT_GRAY,
74
+ },
75
+ dragonRiver: {
76
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/164-2.jpg",
77
+ width: 4021,
78
+ height: 4021,
79
+ avgColor: BgColors.LIGHT_GRAY,
80
+ },
81
+ waterLine: {
82
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/p2704851973.webp",
83
+ thumbnailSrc:
84
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/p2704851973.webp?x-oss-process=style/thumbnail",
85
+ renderedWidth: 500,
86
+ width: 1080,
87
+ height: 720,
88
+ avgColor: BgColors.LIGHT_GRAY,
89
+ },
90
+ phone: {
91
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/301/DSCF1355.RAF.min.jpg",
92
+ width: 924,
93
+ height: 619,
94
+ avgColor: BgColors.LIGHT_GRAY,
95
+ },
96
+ riverAndBoats: {
97
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/x2705749244.jpg",
98
+ renderedWidth: 800,
99
+ width: 1080,
100
+ height: 830,
101
+ avgColor: BgColors.LIGHT_GRAY,
102
+ },
103
+ riverSide: {
104
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/x2705752731.jpg",
105
+ renderedWidth: 400,
106
+ width: 1080,
107
+ height: 720,
108
+ avgColor: BgColors.LIGHT_GRAY,
109
+ },
110
+ quilt: {
111
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/x2710816755.jpg",
112
+ thumbnailSrc:
113
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/x2710816755.jpg?x-oss-process=style/thumbnail",
114
+ renderedWidth: 490,
115
+ width: 1080,
116
+ height: 832,
117
+ avgColor: BgColors.LIGHT_GRAY,
118
+ },
119
+ bridge: {
120
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/p2705529760.webp",
121
+ thumbnailSrc:
122
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/p2705529760.webp?x-oss-process=style/thumbnail",
123
+ renderedWidth: 450,
124
+ width: 1080,
125
+ height: 726,
126
+ avgColor: BgColors.LIGHT_GRAY,
127
+ },
128
+ building: {
129
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20211025194518.jpg",
130
+ thumbnailSrc:
131
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20211025194518.jpg?x-oss-process=style/thumbnail",
132
+ width: 3019,
133
+ height: 2293,
134
+ avgColor: BgColors.LIGHT_GRAY,
135
+ },
136
+ chair: {
137
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/301/room-301.jpg",
138
+ renderedWidth: 490,
139
+ width: 970,
140
+ height: 745,
141
+ avgColor: BgColors.LIGHT_GRAY,
142
+ },
143
+ smoking: {
144
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/DSCF1383.jpg",
145
+ width: 2023,
146
+ height: 2670,
147
+ avgColor: BgColors.LIGHT_GRAY,
148
+ },
149
+ jzBridge: {
150
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/xiang-jiang-river/DSCF1401.jpg",
151
+ width: 5980,
152
+ height: 3699,
153
+ renderedWidth: 700,
154
+ avgColor: BgColors.LIGHT_GRAY,
155
+ },
156
+ motorcycle: {
157
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/4688FF3F-8EF5-4F63-B726-9AC275C1A97E-50268-000009856F7D5885.jpg",
158
+ thumbnailSrc:
159
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/4688FF3F-8EF5-4F63-B726-9AC275C1A97E-50268-000009856F7D5885.jpg?x-oss-process=style/thumbnail",
160
+ width: 1306,
161
+ height: 821,
162
+ avgColor: BgColors.LIGHT_GRAY,
163
+ },
164
+ cycle: {
165
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/3922C86B-79D5-455F-9FA8-7EB405CE95A6-38852-000007863DB50E30.jpg",
166
+ thumbnailSrc:
167
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/3922C86B-79D5-455F-9FA8-7EB405CE95A6-38852-000007863DB50E30.jpg?x-oss-process=style/thumbnail",
168
+ renderedWidth: 400,
169
+ width: 1501,
170
+ height: 1144,
171
+ avgColor: BgColors.LIGHT_GRAY,
172
+ },
173
+ streetGames: {
174
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/B3AACBCA-807B-44C0-9CA2-E1F7E0C00C93_black.jpg",
175
+ thumbnailSrc:
176
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/B3AACBCA-807B-44C0-9CA2-E1F7E0C00C93_black.jpg?x-oss-process=style/thumbnail",
177
+ width: 898,
178
+ height: 729,
179
+ avgColor: BgColors.LIGHT_GRAY,
180
+ },
181
+ corner: {
182
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/E2FDA467-AD6D-4410-9B50-66E1624C13D6-38852-0000078630EDA7C4.jpg",
183
+ thumbnailSrc:
184
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/E2FDA467-AD6D-4410-9B50-66E1624C13D6-38852-0000078630EDA7C4.jpg?x-oss-process=style/thumbnail",
185
+ renderedWidth: 500,
186
+ width: 1776,
187
+ height: 1184,
188
+ avgColor: BgColors.LIGHT_GRAY,
189
+ },
190
+ localDishes: {
191
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/IMG_3869.JPG",
192
+ thumbnailSrc:
193
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/county-town/IMG_3869.JPG?x-oss-process=style/thumbnail",
194
+ renderedWidth: 490,
195
+ width: 897,
196
+ height: 720,
197
+ avgColor: BgColors.LIGHT_GRAY,
198
+ },
199
+ oldMan: {
200
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/before-the-light/IMG_1844.jpg?x-oss-process=style/webp",
201
+ thumbnailSrc:
202
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/before-the-light/IMG_1844.jpg?x-oss-process=style/thumbnail",
203
+ renderedWidth: 400,
204
+ width: 2673,
205
+ height: 3564,
206
+ avgColor: BgColors.LIGHT_GRAY,
207
+ },
208
+ oldWomen: {
209
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/before-the-light/IMG_E1668.JPG?x-oss-process=style/webp",
210
+ thumbnailSrc:
211
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/before-the-light/IMG_E1668.JPG?x-oss-process=style/thumbnail",
212
+ width: 1325,
213
+ height: 1960,
214
+ avgColor: BgColors.LIGHT_GRAY,
215
+ },
216
+ littleChild: {
217
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/before-the-light/IMG_E1677.JPG",
218
+ thumbnailSrc:
219
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/before-the-light/IMG_E1677.JPG?x-oss-process=style/thumbnail",
220
+ width: 2801,
221
+ renderedWidth: 600,
222
+ height: 2801,
223
+ avgColor: BgColors.LIGHT_GRAY,
224
+ },
225
+ logoPreview: {
226
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/illustration/illustration/favicon.png",
227
+ width: 640,
228
+ height: 640,
229
+ avgColor: BgColors.LIGHT_GRAY,
230
+ },
231
+ validLogoExample: {
232
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/illustration/illustration/Logo-with-image.png",
233
+ width: 1092,
234
+ height: 1386,
235
+ avgColor: BgColors.LIGHT_GRAY,
236
+ },
237
+ logoVariants: {
238
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/illustration/illustration/valid-variations.png",
239
+ width: 2800,
240
+ height: 640,
241
+ avgColor: BgColors.LIGHT_GRAY,
242
+ },
243
+ badLogoExamples: {
244
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/illustration/illustration/Bad-Examples.png",
245
+ width: 2801,
246
+ height: 1362,
247
+ avgColor: BgColors.LIGHT_GRAY,
248
+ },
249
+ logoColors: {
250
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/illustration/illustration/colors.png",
251
+ thumbnailSrc:
252
+ "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/illustration/illustration/colors.png?x-oss-process=style/thumbnail",
253
+ width: 2466,
254
+ height: 640,
255
+ avgColor: BgColors.LIGHT_GRAY,
256
+ },
257
+ logoExcludesZone: {
258
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/image/illustration/illustration/Logo-Clear-Area.png",
259
+ width: 1000,
260
+ height: 1000,
261
+ avgColor: BgColors.LIGHT_GRAY,
262
+ },
263
+ };
264
+
265
+ export const PHOTOS_FOR_DEMO = [
266
+ OSS_PHOTOS.riverSide,
267
+ OSS_PHOTOS.stone,
268
+ OSS_PHOTOS.chair,
269
+ OSS_PHOTOS.weapons,
270
+ ];
@@ -0,0 +1,24 @@
1
+ export const ROUTES = {
2
+ INDEX: "/",
3
+ CONTENT: "/blog",
4
+ HELP: "/blog/说明书",
5
+ TAGS: "/tags",
6
+ BLOG: "/blog",
7
+ };
8
+
9
+ export const ROUTE_NAME = {
10
+ [ROUTES.CONTENT]: "目录",
11
+ [ROUTES.BLOG]: "文章",
12
+ unknown: "未知",
13
+ };
14
+
15
+ export const GITHUB_REPO_ADDRESS = "https://github.com/bbbottle/bbki.ng";
16
+ export const OSS_ADDRESS = "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com";
17
+ export const API_ENDPOINT = "https://api.bbki.ng";
18
+ export const API = {
19
+ PROJECTS: "projects",
20
+ UPLOAD_IMG: "upload",
21
+ MOVIES: "movies",
22
+ IMAGES: "images",
23
+ BOOKS: "books",
24
+ };
@@ -0,0 +1,16 @@
1
+ export const VIDEO_LOGS = [
2
+ {
3
+ name: "2021-09-10",
4
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/video/2021-09-10",
5
+ },
6
+ {
7
+ name: "2020-09-18",
8
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/video/2021-09-18.mov",
9
+ },
10
+ {
11
+ name: "2020-09-28",
12
+ src: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/video/2021-09-28-4k30H.mov",
13
+ },
14
+ ];
15
+
16
+ export const VIDEO_TAG_ASPECT_RATIO = 0.5624910522548318;
@@ -0,0 +1,15 @@
1
+ import React, { ReactNode } from "react";
2
+
3
+ export const DemoBox = (props: {
4
+ children?: ReactNode;
5
+ style?: React.CSSProperties;
6
+ }) => {
7
+ return (
8
+ <div
9
+ className="grid place-items-center md:p-32 border-gray-400 aspect-square border border-dotted"
10
+ style={props.style || {}}
11
+ >
12
+ {props.children}
13
+ </div>
14
+ );
15
+ };
@@ -0,0 +1,34 @@
1
+ import React, { useState } from "react";
2
+ import { Button, Img, ImgProps } from "@bbki.ng/components";
3
+ import { PHOTOS_FOR_DEMO } from "@/constants/photos";
4
+ import { DemoBox } from "@/demo/DemoBox";
5
+ import { Photo } from "@/types/photo";
6
+
7
+ const ImgWrapper = (props: ImgProps) => {
8
+ return (
9
+ <DemoBox>
10
+ <Img {...props} />
11
+ </DemoBox>
12
+ );
13
+ };
14
+
15
+ export const ImgDemo = () => {
16
+ const [count, setCount] = useState(0);
17
+ const refresh = () => {
18
+ setCount(count + 1);
19
+ };
20
+
21
+ const images: Photo[] = PHOTOS_FOR_DEMO;
22
+
23
+ return (
24
+ <div>
25
+ <ImgWrapper
26
+ {...images[count % images.length]}
27
+ key={count}
28
+ />
29
+ <Button onClick={refresh} className="mx-32 my-16">
30
+ 刷新
31
+ </Button>
32
+ </div>
33
+ );
34
+ };
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { DemoBox } from "@/demo/DemoBox.js";
3
+ import { Spinner } from "@/components/Spinner";
4
+
5
+ export const SpinnerDemo = () => {
6
+ return (
7
+ <DemoBox style={{ background: "#dc5530", borderColor: "white" }}>
8
+ <Spinner
9
+ disableDotIndicator
10
+ offset={0}
11
+ length={0.4}
12
+ color={[255, 255, 255, 1]}
13
+ multiplier={20000}
14
+ />
15
+ </DemoBox>
16
+ );
17
+ };
@@ -0,0 +1,8 @@
1
+ declare module "*.mdx" {
2
+ let MDXComponent: (props: any) => JSX.Element;
3
+ export default MDXComponent;
4
+ export const meta: {
5
+ tags?: string[];
6
+ title: string;
7
+ };
8
+ }
@@ -0,0 +1,27 @@
1
+ import React, {
2
+ createContext,
3
+ ReactNode,
4
+ useState,
5
+ Dispatch,
6
+ SetStateAction,
7
+ } from "react";
8
+
9
+ type LoadingContext = {
10
+ isLoading: boolean;
11
+ setIsLoading: Dispatch<SetStateAction<boolean>>;
12
+ };
13
+
14
+ export const GlobalLoadingContext = createContext<LoadingContext>({
15
+ isLoading: false,
16
+ setIsLoading: () => false,
17
+ });
18
+
19
+ export const GlobalLoadingStateProvider = (props: { children: ReactNode }) => {
20
+ const [isLoading, setIsLoading] = useState(false);
21
+
22
+ return (
23
+ <GlobalLoadingContext.Provider value={{ isLoading, setIsLoading }}>
24
+ {props.children}
25
+ </GlobalLoadingContext.Provider>
26
+ );
27
+ };
@@ -0,0 +1,15 @@
1
+ import { buildSimpleApiHooks } from "@/utils";
2
+ import { API } from "@/constants/routes";
3
+
4
+ export { usePaths } from "./use_paths";
5
+ export { useRouteName } from "./use_route_name";
6
+ export { useImgLoading } from "./use_img_loading";
7
+
8
+ export {
9
+ useVideoControls,
10
+ useVideoProgress,
11
+ useVideoEleHeight,
12
+ } from "./use_video_controls";
13
+
14
+ export const useMovies = buildSimpleApiHooks(API.MOVIES, "movies");
15
+ export const useBooks = buildSimpleApiHooks(API.BOOKS, "books");
@@ -0,0 +1,24 @@
1
+ import { useLocation } from "react-router-dom";
2
+ import { useEffect } from "react";
3
+
4
+ export const useScrollToTop = (excludePath = "") => {
5
+ const { pathname } = useLocation();
6
+
7
+ const resetScroll = () => {
8
+ if (excludePath && pathname.includes(excludePath)) {
9
+ return;
10
+ }
11
+ setTimeout(() => {
12
+ window.scrollTo(0, 0);
13
+ }, 0);
14
+ };
15
+
16
+ useEffect(() => {
17
+ window.addEventListener("popstate", resetScroll);
18
+ return () => {
19
+ window.removeEventListener("popstate", resetScroll);
20
+ };
21
+ }, []);
22
+
23
+ useEffect(resetScroll, [pathname]);
24
+ };
@@ -0,0 +1,36 @@
1
+ import React, { useEffect } from "react";
2
+ import classnames from "classnames";
3
+
4
+ interface TransOption {
5
+ originCls?: string;
6
+ opacity?: boolean;
7
+ offset?: boolean;
8
+ blur?: boolean;
9
+ }
10
+
11
+ const defaultOpt = {
12
+ originCls: "",
13
+ opacity: true,
14
+ offset: true,
15
+ blur: true,
16
+ };
17
+
18
+ export const useTransitionCls = (options: TransOption = defaultOpt) => {
19
+ const [visible, setVisible] = React.useState(false);
20
+ const { originCls, opacity, offset, blur } = options;
21
+
22
+ const cls = classnames(originCls, "transition-all", "duration-500", {
23
+ "blur-sm": !visible && blur,
24
+ "blur-none": visible && blur,
25
+ "translate-y-0": visible && offset,
26
+ "translate-y-8": !visible && offset,
27
+ "opacity-10": !visible && opacity,
28
+ "opacity-100": visible && opacity,
29
+ });
30
+
31
+ useEffect(() => {
32
+ setVisible(true);
33
+ }, []);
34
+
35
+ return cls;
36
+ };