@san-siva/blogkit 1.1.0 → 1.1.1
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/dist/cjs/dynamicComponents/BlogDynamic.js +29 -18
- package/dist/cjs/dynamicComponents/BlogDynamic.js.map +1 -1
- package/dist/cjs/index.css +1 -1
- package/dist/cjs/index.css.map +1 -1
- package/dist/esm/dynamicComponents/BlogDynamic.js +29 -18
- package/dist/esm/dynamicComponents/BlogDynamic.js.map +1 -1
- package/dist/esm/index.css +1 -1
- package/dist/esm/index.css.map +1 -1
- package/dist/types/dynamicComponents/BlogDynamic.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/dynamicComponents/BlogDynamic.tsx +65 -58
- package/src/styles/Blog.module.scss +4 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlogDynamic.d.ts","sourceRoot":"","sources":["../../../src/dynamicComponents/BlogDynamic.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BlogDynamic.d.ts","sourceRoot":"","sources":["../../../src/dynamicComponents/BlogDynamic.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAc,SAAS,EAAiB,MAAM,OAAO,CAAC;AAIlE,UAAU,cAAc;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,cAAc,EAAE,CAAC;CAC5B;AAgBD,QAAA,MAAM,IAAI,GAAI,qBAAyC,cAAc,4CA4NpE,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@san-siva/blogkit",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "A reusable blog component library for React/Next.js applications with code highlighting, diagrams, and rich content features",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
useRef,
|
|
10
10
|
useState,
|
|
11
11
|
} from 'react';
|
|
12
|
+
import { useSpring, animated } from '@react-spring/web';
|
|
12
13
|
|
|
13
14
|
import type { MouseEvent, ReactNode, RefAttributes } from 'react';
|
|
14
15
|
|
|
@@ -38,34 +39,22 @@ interface CategoryTitleValue extends SectionReferenceValue {
|
|
|
38
39
|
|
|
39
40
|
type CategoryTitle = Map<string, CategoryTitleValue>;
|
|
40
41
|
|
|
41
|
-
type AddPaddingTopTimerReference = ReturnType<typeof setTimeout> | null;
|
|
42
|
-
|
|
43
42
|
const Blog = ({ children, title = 'In this article' }: BlogProperties) => {
|
|
44
|
-
const addPaddingTopTimerReference = useRef<AddPaddingTopTimerReference>(null);
|
|
45
|
-
const highlightCategoryTimerReference =
|
|
46
|
-
useRef<AddPaddingTopTimerReference>(null);
|
|
47
|
-
|
|
48
|
-
const clearTimers = (
|
|
49
|
-
addPaddingTopTimerReference_: AddPaddingTopTimerReference,
|
|
50
|
-
highlightCategoryTimerReference_: AddPaddingTopTimerReference
|
|
51
|
-
) => {
|
|
52
|
-
if (addPaddingTopTimerReference_) {
|
|
53
|
-
clearTimeout(addPaddingTopTimerReference_);
|
|
54
|
-
}
|
|
55
|
-
if (highlightCategoryTimerReference_) {
|
|
56
|
-
clearTimeout(highlightCategoryTimerReference_);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
43
|
const sectionReferences = useRef<SectionReference>(new Map());
|
|
61
44
|
const [categoryTitles, setCategoryTitles] = useState<CategoryTitle>(
|
|
62
45
|
new Map()
|
|
63
46
|
);
|
|
64
47
|
const [visibleTitle, setVisibleTitle] = useState<string | null>(null);
|
|
48
|
+
const [showTOC, setShowTOC] = useState(false);
|
|
49
|
+
|
|
65
50
|
const updateTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
51
|
+
const showTOCTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
66
52
|
|
|
67
53
|
const sortByDomPosition = useCallback(
|
|
68
|
-
(
|
|
54
|
+
(
|
|
55
|
+
[, a]: [string, SectionReferenceValue],
|
|
56
|
+
[, b]: [string, SectionReferenceValue]
|
|
57
|
+
) => {
|
|
69
58
|
const position = a.el.compareDocumentPosition(b.el);
|
|
70
59
|
if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
71
60
|
return -1; // a comes before b
|
|
@@ -77,6 +66,16 @@ const Blog = ({ children, title = 'In this article' }: BlogProperties) => {
|
|
|
77
66
|
[]
|
|
78
67
|
);
|
|
79
68
|
|
|
69
|
+
const debounceShowTOC = useCallback(() => {
|
|
70
|
+
if (showTOC) return;
|
|
71
|
+
if (showTOCTimerRef.current) {
|
|
72
|
+
clearTimeout(showTOCTimerRef.current);
|
|
73
|
+
}
|
|
74
|
+
showTOCTimerRef.current = setTimeout(() => {
|
|
75
|
+
setShowTOC(true);
|
|
76
|
+
}, 200);
|
|
77
|
+
}, [showTOC]);
|
|
78
|
+
|
|
80
79
|
const updateCategoryTitles = useCallback(() => {
|
|
81
80
|
const now = Date.now();
|
|
82
81
|
const newCategoryTitles = new Map<string, CategoryTitleValue>();
|
|
@@ -98,12 +97,13 @@ const Blog = ({ children, title = 'In this article' }: BlogProperties) => {
|
|
|
98
97
|
});
|
|
99
98
|
}
|
|
100
99
|
|
|
101
|
-
if (newCategoryTitles.size
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
if (newCategoryTitles.size === 0) return;
|
|
101
|
+
|
|
102
|
+
setCategoryTitles(newCategoryTitles);
|
|
103
|
+
debounceShowTOC();
|
|
104
|
+
|
|
105
|
+
if (visibleTitle) return;
|
|
106
|
+
setVisibleTitle(firstSectionId);
|
|
107
107
|
}, [visibleTitle, sortByDomPosition]);
|
|
108
108
|
|
|
109
109
|
const debounceUpdateCategoryTitles = useCallback(() => {
|
|
@@ -142,51 +142,53 @@ const Blog = ({ children, title = 'In this article' }: BlogProperties) => {
|
|
|
142
142
|
|
|
143
143
|
useEffect(() => {
|
|
144
144
|
return () => {
|
|
145
|
-
clearTimers(
|
|
146
|
-
addPaddingTopTimerReference.current,
|
|
147
|
-
highlightCategoryTimerReference.current
|
|
148
|
-
);
|
|
149
145
|
if (updateTimerRef.current) {
|
|
150
146
|
clearTimeout(updateTimerRef.current);
|
|
151
147
|
}
|
|
148
|
+
if (showTOCTimerRef.current) {
|
|
149
|
+
clearTimeout(showTOCTimerRef.current);
|
|
150
|
+
}
|
|
152
151
|
};
|
|
153
152
|
}, []);
|
|
154
153
|
|
|
155
|
-
const handleSectionReference = useCallback(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
// Add parent section reference
|
|
160
|
-
if (parentRef) {
|
|
161
|
-
const id = parentRef.dataset.id;
|
|
162
|
-
const title = parentRef.dataset.title;
|
|
163
|
-
if (id && title) {
|
|
164
|
-
sectionReferences.current.set(id, {
|
|
165
|
-
el: parentRef,
|
|
166
|
-
title,
|
|
167
|
-
isSubSection: false,
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
}
|
|
154
|
+
const handleSectionReference = useCallback(
|
|
155
|
+
(element: ForwardedReference) => {
|
|
156
|
+
if (!element) return;
|
|
157
|
+
const { parentRef, childRefs } = element;
|
|
171
158
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const id = childRef.dataset.id;
|
|
177
|
-
const title = childRef.dataset.title;
|
|
159
|
+
// Add parent section reference
|
|
160
|
+
if (parentRef) {
|
|
161
|
+
const id = parentRef.dataset.id;
|
|
162
|
+
const title = parentRef.dataset.title;
|
|
178
163
|
if (id && title) {
|
|
179
164
|
sectionReferences.current.set(id, {
|
|
180
|
-
el:
|
|
165
|
+
el: parentRef,
|
|
181
166
|
title,
|
|
182
|
-
isSubSection:
|
|
167
|
+
isSubSection: false,
|
|
183
168
|
});
|
|
184
169
|
}
|
|
185
170
|
}
|
|
186
|
-
}
|
|
187
171
|
|
|
188
|
-
|
|
189
|
-
|
|
172
|
+
// Add child section references
|
|
173
|
+
if (Array.isArray(childRefs)) {
|
|
174
|
+
for (const childRef of childRefs) {
|
|
175
|
+
if (!childRef) continue;
|
|
176
|
+
const id = childRef.dataset.id;
|
|
177
|
+
const title = childRef.dataset.title;
|
|
178
|
+
if (id && title) {
|
|
179
|
+
sectionReferences.current.set(id, {
|
|
180
|
+
el: childRef,
|
|
181
|
+
title,
|
|
182
|
+
isSubSection: true,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
debounceUpdateCategoryTitles();
|
|
189
|
+
},
|
|
190
|
+
[debounceUpdateCategoryTitles]
|
|
191
|
+
);
|
|
190
192
|
|
|
191
193
|
const handleClickCategoryTitle = (
|
|
192
194
|
error: MouseEvent<HTMLParagraphElement>
|
|
@@ -210,6 +212,11 @@ const Blog = ({ children, title = 'In this article' }: BlogProperties) => {
|
|
|
210
212
|
}, 1000);
|
|
211
213
|
};
|
|
212
214
|
|
|
215
|
+
const sidebarStyle = useSpring({
|
|
216
|
+
opacity: showTOC ? 1 : 0,
|
|
217
|
+
transform: showTOC ? 'translateX(0)' : 'translateX(80px)',
|
|
218
|
+
config: { tension: 280, friction: 60 },
|
|
219
|
+
});
|
|
213
220
|
|
|
214
221
|
return (
|
|
215
222
|
<div className={styles.blog}>
|
|
@@ -221,7 +228,7 @@ const Blog = ({ children, title = 'In this article' }: BlogProperties) => {
|
|
|
221
228
|
} as RefAttributes<ForwardedReference>);
|
|
222
229
|
})}
|
|
223
230
|
</div>
|
|
224
|
-
<div className={styles['blog__sidebar']}>
|
|
231
|
+
<animated.div className={styles['blog__sidebar']} style={sidebarStyle}>
|
|
225
232
|
<p
|
|
226
233
|
className={`${styles['margin-bottom--3']} ${styles['category__header']}`}
|
|
227
234
|
>
|
|
@@ -249,7 +256,7 @@ const Blog = ({ children, title = 'In this article' }: BlogProperties) => {
|
|
|
249
256
|
);
|
|
250
257
|
}
|
|
251
258
|
)}
|
|
252
|
-
</div>
|
|
259
|
+
</animated.div>
|
|
253
260
|
</div>
|
|
254
261
|
);
|
|
255
262
|
};
|
|
@@ -21,11 +21,13 @@
|
|
|
21
21
|
top: calc(var(--topbar-height) + #{styles.space(6)});
|
|
22
22
|
padding: styles.space(6);
|
|
23
23
|
min-width: calc(
|
|
24
|
-
#{styles.rem(
|
|
24
|
+
#{styles.rem(320)} - #{styles.space(6)} - #{styles.space(6)}
|
|
25
25
|
);
|
|
26
26
|
border-radius: styles.$border-radius--1;
|
|
27
27
|
background-color: styles.$color--code;
|
|
28
|
-
|
|
28
|
+
box-shadow:
|
|
29
|
+
0 0 0 1px styles.$color--border,
|
|
30
|
+
0 styles.space(1) styles.space(2) 0 styles.$color--border;
|
|
29
31
|
|
|
30
32
|
margin-left: styles.space(9);
|
|
31
33
|
|