fumadocs-core 16.4.1 → 16.4.2
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/advanced-BRT5Ij43.js +80 -0
- package/dist/advanced-BRT5Ij43.js.map +1 -0
- package/dist/algolia-CBBN8R6-.d.ts +68 -0
- package/dist/algolia-CBBN8R6-.d.ts.map +1 -0
- package/dist/algolia-CQPXCnjV.js +49 -0
- package/dist/algolia-CQPXCnjV.js.map +1 -0
- package/dist/breadcrumb.d.ts +29 -27
- package/dist/breadcrumb.d.ts.map +1 -0
- package/dist/breadcrumb.js +55 -72
- package/dist/breadcrumb.js.map +1 -0
- package/dist/chunk-B-ezknvj.js +42 -0
- package/dist/codeblock-utils-lld8UiQo.d.ts +37 -0
- package/dist/codeblock-utils-lld8UiQo.d.ts.map +1 -0
- package/dist/content/github.d.ts +43 -32
- package/dist/content/github.d.ts.map +1 -0
- package/dist/content/github.js +29 -43
- package/dist/content/github.js.map +1 -0
- package/dist/content/index.d.ts +20 -13
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +17 -23
- package/dist/content/index.js.map +1 -0
- package/dist/content/mdx/preset-bundler.d.ts +22 -24
- package/dist/content/mdx/preset-bundler.d.ts.map +1 -0
- package/dist/content/mdx/preset-bundler.js +38 -69
- package/dist/content/mdx/preset-bundler.js.map +1 -0
- package/dist/content/mdx/preset-runtime.d.ts +22 -24
- package/dist/content/mdx/preset-runtime.d.ts.map +1 -0
- package/dist/content/mdx/preset-runtime.js +36 -68
- package/dist/content/mdx/preset-runtime.js.map +1 -0
- package/dist/content/toc.d.ts +7 -6
- package/dist/content/toc.d.ts.map +1 -0
- package/dist/content/toc.js +15 -19
- package/dist/content/toc.js.map +1 -0
- package/dist/definitions-DuxDer_c.d.ts +62 -0
- package/dist/definitions-DuxDer_c.d.ts.map +1 -0
- package/dist/dynamic-link.d.ts +7 -5
- package/dist/dynamic-link.d.ts.map +1 -0
- package/dist/dynamic-link.js +29 -27
- package/dist/dynamic-link.js.map +1 -0
- package/dist/fetch-B5e9CFfN.js +20 -0
- package/dist/fetch-B5e9CFfN.js.map +1 -0
- package/dist/framework/index.d.ts +38 -29
- package/dist/framework/index.d.ts.map +1 -0
- package/dist/framework/index.js +68 -17
- package/dist/framework/index.js.map +1 -0
- package/dist/framework/next.d.ts +15 -10
- package/dist/framework/next.d.ts.map +1 -0
- package/dist/framework/next.js +18 -26
- package/dist/framework/next.js.map +1 -0
- package/dist/framework/react-router.d.ts +15 -10
- package/dist/framework/react-router.d.ts.map +1 -0
- package/dist/framework/react-router.js +42 -55
- package/dist/framework/react-router.js.map +1 -0
- package/dist/framework/tanstack.d.ts +15 -10
- package/dist/framework/tanstack.d.ts.map +1 -0
- package/dist/framework/tanstack.js +54 -69
- package/dist/framework/tanstack.js.map +1 -0
- package/dist/framework/waku.d.ts +15 -10
- package/dist/framework/waku.d.ts.map +1 -0
- package/dist/framework/waku.js +47 -58
- package/dist/framework/waku.js.map +1 -0
- package/dist/highlight/client.d.ts +6 -7
- package/dist/highlight/client.d.ts.map +1 -0
- package/dist/highlight/client.js +22 -14
- package/dist/highlight/client.js.map +1 -0
- package/dist/highlight/index.d.ts +2 -30
- package/dist/highlight/index.js +3 -13
- package/dist/i18n/index.d.ts +2 -39
- package/dist/i18n/index.js +6 -7
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/middleware.d.ts +36 -28
- package/dist/i18n/middleware.d.ts.map +1 -0
- package/dist/i18n/middleware.js +55 -73
- package/dist/i18n/middleware.js.map +1 -0
- package/dist/icon-Dt7IObrc.js +19 -0
- package/dist/icon-Dt7IObrc.js.map +1 -0
- package/dist/index-2U6Tl4--.d.ts +379 -0
- package/dist/index-2U6Tl4--.d.ts.map +1 -0
- package/dist/index-Bw-DCOra.d.ts +41 -0
- package/dist/index-Bw-DCOra.d.ts.map +1 -0
- package/dist/link.d.ts +17 -15
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +29 -9
- package/dist/link.js.map +1 -0
- package/dist/mdast-utils-mc9-X-PK.js +40 -0
- package/dist/mdast-utils-mc9-X-PK.js.map +1 -0
- package/dist/mdx-plugins/codeblock-utils.d.ts +2 -29
- package/dist/mdx-plugins/codeblock-utils.js +71 -9
- package/dist/mdx-plugins/codeblock-utils.js.map +1 -0
- package/dist/mdx-plugins/index.d.ts +15 -20
- package/dist/mdx-plugins/index.js +18 -73
- package/dist/mdx-plugins/rehype-code.d.ts +2 -55
- package/dist/mdx-plugins/rehype-code.js +5 -15
- package/dist/mdx-plugins/rehype-toc.d.ts +2 -14
- package/dist/mdx-plugins/rehype-toc.js +3 -7
- package/dist/mdx-plugins/remark-admonition.d.ts +2 -20
- package/dist/mdx-plugins/remark-admonition.js +74 -8
- package/dist/mdx-plugins/remark-admonition.js.map +1 -0
- package/dist/mdx-plugins/remark-code-tab.d.ts +2 -30
- package/dist/mdx-plugins/remark-code-tab.js +183 -7
- package/dist/mdx-plugins/remark-code-tab.js.map +1 -0
- package/dist/mdx-plugins/remark-directive-admonition.d.ts +2 -27
- package/dist/mdx-plugins/remark-directive-admonition.js +60 -7
- package/dist/mdx-plugins/remark-directive-admonition.js.map +1 -0
- package/dist/mdx-plugins/remark-gfm.d.ts +2 -1
- package/dist/mdx-plugins/remark-gfm.js +3 -7
- package/dist/mdx-plugins/remark-heading.d.ts +2 -31
- package/dist/mdx-plugins/remark-heading.js +45 -8
- package/dist/mdx-plugins/remark-heading.js.map +1 -0
- package/dist/mdx-plugins/remark-image.d.ts +2 -57
- package/dist/mdx-plugins/remark-image.js +192 -7
- package/dist/mdx-plugins/remark-image.js.map +1 -0
- package/dist/mdx-plugins/remark-mdx-files.d.ts +2 -40
- package/dist/mdx-plugins/remark-mdx-files.js +187 -7
- package/dist/mdx-plugins/remark-mdx-files.js.map +1 -0
- package/dist/mdx-plugins/remark-mdx-mermaid.d.ts +2 -15
- package/dist/mdx-plugins/remark-mdx-mermaid.js +31 -7
- package/dist/mdx-plugins/remark-mdx-mermaid.js.map +1 -0
- package/dist/mdx-plugins/remark-npm.d.ts +2 -31
- package/dist/mdx-plugins/remark-npm.js +68 -8
- package/dist/mdx-plugins/remark-npm.js.map +1 -0
- package/dist/mdx-plugins/remark-steps.d.ts +2 -23
- package/dist/mdx-plugins/remark-steps.js +77 -7
- package/dist/mdx-plugins/remark-steps.js.map +1 -0
- package/dist/mdx-plugins/remark-structure.d.ts +2 -71
- package/dist/mdx-plugins/remark-structure.js +105 -11
- package/dist/mdx-plugins/remark-structure.js.map +1 -0
- package/dist/mixedbread-DlByNYSd.js +88 -0
- package/dist/mixedbread-DlByNYSd.js.map +1 -0
- package/dist/negotiation/index.d.ts +6 -4
- package/dist/negotiation/index.d.ts.map +1 -0
- package/dist/negotiation/index.js +41 -11
- package/dist/negotiation/index.js.map +1 -0
- package/dist/normalize-url-DP9-1I-S.js +16 -0
- package/dist/normalize-url-DP9-1I-S.js.map +1 -0
- package/dist/orama-cloud-DH3g37zc.js +84 -0
- package/dist/orama-cloud-DH3g37zc.js.map +1 -0
- package/dist/page-tree/index.d.ts +23 -11
- package/dist/page-tree/index.d.ts.map +1 -0
- package/dist/page-tree/index.js +3 -17
- package/dist/path-DHIjrDBP.js +60 -0
- package/dist/path-DHIjrDBP.js.map +1 -0
- package/dist/rehype-code-CdiZ1Y6P.js +241 -0
- package/dist/rehype-code-CdiZ1Y6P.js.map +1 -0
- package/dist/rehype-code-vVWG4-ej.d.ts +58 -0
- package/dist/rehype-code-vVWG4-ej.d.ts.map +1 -0
- package/dist/rehype-toc-DJvSyE0o.d.ts +18 -0
- package/dist/rehype-toc-DJvSyE0o.d.ts.map +1 -0
- package/dist/rehype-toc-DVwJcwvA.js +143 -0
- package/dist/rehype-toc-DVwJcwvA.js.map +1 -0
- package/dist/remark-admonition-DOwBWzsH.d.ts +22 -0
- package/dist/remark-admonition-DOwBWzsH.d.ts.map +1 -0
- package/dist/remark-code-tab-CXsYlims.d.ts +32 -0
- package/dist/remark-code-tab-CXsYlims.d.ts.map +1 -0
- package/dist/remark-directive-admonition-BCm_yiU9.d.ts +36 -0
- package/dist/remark-directive-admonition-BCm_yiU9.d.ts.map +1 -0
- package/dist/remark-gfm-CeWpMwyk.d.ts +2 -0
- package/dist/remark-heading-CXvCY0go.d.ts +37 -0
- package/dist/remark-heading-CXvCY0go.d.ts.map +1 -0
- package/dist/remark-image-CvUis4R1.d.ts +65 -0
- package/dist/remark-image-CvUis4R1.d.ts.map +1 -0
- package/dist/remark-mdx-files-B31xFFG4.d.ts +56 -0
- package/dist/remark-mdx-files-B31xFFG4.d.ts.map +1 -0
- package/dist/remark-mdx-mermaid-BdSUUiCG.d.ts +17 -0
- package/dist/remark-mdx-mermaid-BdSUUiCG.d.ts.map +1 -0
- package/dist/remark-npm-BIvIEKT2.d.ts +36 -0
- package/dist/remark-npm-BIvIEKT2.d.ts.map +1 -0
- package/dist/remark-steps-CHJN-rtm.d.ts +28 -0
- package/dist/remark-steps-CHJN-rtm.d.ts.map +1 -0
- package/dist/remark-structure-RZD2gGKp.d.ts +77 -0
- package/dist/remark-structure-RZD2gGKp.d.ts.map +1 -0
- package/dist/remove-undefined-Cfs4o_mM.js +19 -0
- package/dist/remove-undefined-Cfs4o_mM.js.map +1 -0
- package/dist/search/algolia.d.ts +3 -69
- package/dist/search/algolia.js +69 -63
- package/dist/search/algolia.js.map +1 -0
- package/dist/search/client.d.ts +120 -114
- package/dist/search/client.d.ts.map +1 -0
- package/dist/search/client.js +92 -91
- package/dist/search/client.js.map +1 -0
- package/dist/search/index.d.ts +20 -18
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +3 -7
- package/dist/search/orama-cloud.d.ts +70 -68
- package/dist/search/orama-cloud.d.ts.map +1 -0
- package/dist/search/orama-cloud.js +46 -54
- package/dist/search/orama-cloud.js.map +1 -0
- package/dist/search/server.d.ts +6 -136
- package/dist/search/server.js +292 -369
- package/dist/search/server.js.map +1 -0
- package/dist/search-D6ChCLhY.js +44 -0
- package/dist/search-D6ChCLhY.js.map +1 -0
- package/dist/server-CPR_fgkH.d.ts +133 -0
- package/dist/server-CPR_fgkH.d.ts.map +1 -0
- package/dist/shiki-4oMYwHED.js +80 -0
- package/dist/shiki-4oMYwHED.js.map +1 -0
- package/dist/shiki-CIBQys54.d.ts +33 -0
- package/dist/shiki-CIBQys54.d.ts.map +1 -0
- package/dist/source/client/index.d.ts +7 -5
- package/dist/source/client/index.d.ts.map +1 -0
- package/dist/source/client/index.js +24 -35
- package/dist/source/client/index.js.map +1 -0
- package/dist/source/index.d.ts +3 -42
- package/dist/source/index.js +599 -752
- package/dist/source/index.js.map +1 -0
- package/dist/source/plugins/lucide-icons.d.ts +7 -7
- package/dist/source/plugins/lucide-icons.d.ts.map +1 -0
- package/dist/source/plugins/lucide-icons.js +21 -20
- package/dist/source/plugins/lucide-icons.js.map +1 -0
- package/dist/source/plugins/slugs.d.ts +3 -0
- package/dist/source/plugins/slugs.js +65 -0
- package/dist/source/plugins/slugs.js.map +1 -0
- package/dist/source/schema.d.ts +17 -14
- package/dist/source/schema.d.ts.map +1 -0
- package/dist/source/schema.js +26 -22
- package/dist/source/schema.js.map +1 -0
- package/dist/static-Dq8pA8Ay.js +51 -0
- package/dist/static-Dq8pA8Ay.js.map +1 -0
- package/dist/toc.d.ts +38 -25
- package/dist/toc.d.ts.map +1 -0
- package/dist/toc.js +123 -136
- package/dist/toc.js.map +1 -0
- package/dist/util-CK2ykiif.d.ts +8 -0
- package/dist/util-CK2ykiif.d.ts.map +1 -0
- package/dist/util-s9piKHsk.js +10 -0
- package/dist/util-s9piKHsk.js.map +1 -0
- package/dist/utils/use-effect-event.d.ts +3 -1
- package/dist/utils/use-effect-event.d.ts.map +1 -0
- package/dist/utils/use-effect-event.js +16 -13
- package/dist/utils/use-effect-event.js.map +1 -0
- package/dist/utils/use-media-query.d.ts +3 -1
- package/dist/utils/use-media-query.d.ts.map +1 -0
- package/dist/utils/use-media-query.js +20 -20
- package/dist/utils/use-media-query.js.map +1 -0
- package/dist/utils/use-on-change.d.ts +3 -1
- package/dist/utils/use-on-change.d.ts.map +1 -0
- package/dist/utils/use-on-change.js +23 -7
- package/dist/utils/use-on-change.js.map +1 -0
- package/dist/utils-DUvi2WkD.js +134 -0
- package/dist/utils-DUvi2WkD.js.map +1 -0
- package/package.json +60 -58
- package/dist/algolia-IZEDLPHE.js +0 -58
- package/dist/chunk-5PMI7QDD.js +0 -220
- package/dist/chunk-ADBHPKXG.js +0 -78
- package/dist/chunk-APKPSBSB.js +0 -74
- package/dist/chunk-CH7YHH7V.js +0 -222
- package/dist/chunk-EFVXL2PP.js +0 -144
- package/dist/chunk-EMWGTXSW.js +0 -19
- package/dist/chunk-FAEPKD7U.js +0 -20
- package/dist/chunk-FUUVPEA5.js +0 -29
- package/dist/chunk-GINBKBVQ.js +0 -12
- package/dist/chunk-GLRQBLGN.js +0 -59
- package/dist/chunk-JUF4WZ6G.js +0 -117
- package/dist/chunk-K4WNLOVQ.js +0 -75
- package/dist/chunk-L4JKQWCM.js +0 -131
- package/dist/chunk-MA6O2UUE.js +0 -50
- package/dist/chunk-ONG4RVCR.js +0 -8
- package/dist/chunk-OTD7MV33.js +0 -53
- package/dist/chunk-PFNP6PEB.js +0 -11
- package/dist/chunk-SH7BNTG7.js +0 -38
- package/dist/chunk-TWIDBWFG.js +0 -84
- package/dist/chunk-U67V476Y.js +0 -35
- package/dist/chunk-VLSDGCJE.js +0 -47
- package/dist/chunk-W6WTLKRA.js +0 -73
- package/dist/chunk-X2HFD5QJ.js +0 -275
- package/dist/chunk-XJ6ZQNEX.js +0 -91
- package/dist/chunk-XN2LKXFZ.js +0 -101
- package/dist/chunk-XOFXGHS4.js +0 -93
- package/dist/chunk-XZSI7AHE.js +0 -67
- package/dist/chunk-YVVDKJ2H.js +0 -34
- package/dist/chunk-ZMWYLUDP.js +0 -21
- package/dist/definitions-pJ7PybYY.d.ts +0 -60
- package/dist/fetch-IBTWQCJR.js +0 -22
- package/dist/loader-_E2HOdV0.d.ts +0 -333
- package/dist/mixedbread-A3WLENES.js +0 -117
- package/dist/orama-cloud-UZAPMPFV.js +0 -93
- package/dist/static-A2YJ5TXV.js +0 -62
- package/dist/util-bZU2QeJ2.d.ts +0 -6
package/dist/toc.js
CHANGED
|
@@ -1,151 +1,138 @@
|
|
|
1
|
-
|
|
2
|
-
import "./chunk-U67V476Y.js";
|
|
1
|
+
'use client';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
createContext,
|
|
7
|
-
useContext,
|
|
8
|
-
useEffect,
|
|
9
|
-
useEffectEvent,
|
|
10
|
-
useLayoutEffect,
|
|
11
|
-
useMemo,
|
|
12
|
-
useRef,
|
|
13
|
-
useState
|
|
14
|
-
} from "react";
|
|
3
|
+
import { createContext, useContext, useEffect, useEffectEvent, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
15
5
|
import scrollIntoView from "scroll-into-view-if-needed";
|
|
16
6
|
|
|
17
|
-
|
|
7
|
+
//#region src/utils/merge-refs.ts
|
|
18
8
|
function mergeRefs(...refs) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
};
|
|
9
|
+
return (value) => {
|
|
10
|
+
refs.forEach((ref) => {
|
|
11
|
+
if (typeof ref === "function") ref(value);
|
|
12
|
+
else if (ref != null) ref.current = value;
|
|
13
|
+
});
|
|
14
|
+
};
|
|
28
15
|
}
|
|
29
16
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/toc.tsx
|
|
19
|
+
const ActiveAnchorContext = createContext([]);
|
|
20
|
+
const ScrollContext = createContext({ current: null });
|
|
21
|
+
/**
|
|
22
|
+
* The estimated active heading ID
|
|
23
|
+
*/
|
|
36
24
|
function useActiveAnchor() {
|
|
37
|
-
|
|
25
|
+
return useContext(ActiveAnchorContext)[0];
|
|
38
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The id of visible anchors
|
|
29
|
+
*/
|
|
39
30
|
function useActiveAnchors() {
|
|
40
|
-
|
|
31
|
+
return useContext(ActiveAnchorContext);
|
|
41
32
|
}
|
|
42
|
-
function ScrollProvider({
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
33
|
+
function ScrollProvider({ containerRef, children }) {
|
|
34
|
+
return /* @__PURE__ */ jsx(ScrollContext.Provider, {
|
|
35
|
+
value: containerRef,
|
|
36
|
+
children
|
|
37
|
+
});
|
|
47
38
|
}
|
|
48
|
-
function AnchorProvider({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return /* @__PURE__ */ jsx(ActiveAnchorContext.Provider, { value: useAnchorObserver(headings, single), children });
|
|
39
|
+
function AnchorProvider({ toc, single = false, children }) {
|
|
40
|
+
const headings = useMemo(() => {
|
|
41
|
+
return toc.map((item) => item.url.split("#")[1]);
|
|
42
|
+
}, [toc]);
|
|
43
|
+
return /* @__PURE__ */ jsx(ActiveAnchorContext.Provider, {
|
|
44
|
+
value: useAnchorObserver(headings, single),
|
|
45
|
+
children
|
|
46
|
+
});
|
|
57
47
|
}
|
|
58
|
-
function TOCItem({
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
48
|
+
function TOCItem({ ref, onActiveChange = () => null, ...props }) {
|
|
49
|
+
const containerRef = useContext(ScrollContext);
|
|
50
|
+
const anchorRef = useRef(null);
|
|
51
|
+
const activeOrder = useActiveAnchors().indexOf(props.href.slice(1));
|
|
52
|
+
const isActive = activeOrder !== -1;
|
|
53
|
+
const shouldScroll = activeOrder === 0;
|
|
54
|
+
const onActiveChangeEvent = useEffectEvent(onActiveChange);
|
|
55
|
+
useLayoutEffect(() => {
|
|
56
|
+
const anchor = anchorRef.current;
|
|
57
|
+
const container = containerRef.current;
|
|
58
|
+
if (container && anchor && shouldScroll) scrollIntoView(anchor, {
|
|
59
|
+
behavior: "smooth",
|
|
60
|
+
block: "center",
|
|
61
|
+
inline: "center",
|
|
62
|
+
scrollMode: "always",
|
|
63
|
+
boundary: container
|
|
64
|
+
});
|
|
65
|
+
}, [containerRef, shouldScroll]);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
return () => onActiveChangeEvent(isActive);
|
|
68
|
+
}, [isActive]);
|
|
69
|
+
return /* @__PURE__ */ jsx("a", {
|
|
70
|
+
ref: mergeRefs(anchorRef, ref),
|
|
71
|
+
"data-active": isActive,
|
|
72
|
+
...props,
|
|
73
|
+
children: props.children
|
|
74
|
+
});
|
|
85
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Find the active heading of page
|
|
78
|
+
*
|
|
79
|
+
* It selects the top heading by default, and the last item when reached the bottom of page.
|
|
80
|
+
*
|
|
81
|
+
* @param watch - An array of element ids to watch
|
|
82
|
+
* @param single - only one active item at most
|
|
83
|
+
* @returns Active anchor
|
|
84
|
+
*/
|
|
86
85
|
function useAnchorObserver(watch, single) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const elements = watch.flatMap(
|
|
136
|
-
(heading) => document.getElementById(heading) ?? []
|
|
137
|
-
);
|
|
138
|
-
for (const element of elements) observer.observe(element);
|
|
139
|
-
return () => {
|
|
140
|
-
for (const element of elements) observer.unobserve(element);
|
|
141
|
-
};
|
|
142
|
-
}, [watch]);
|
|
143
|
-
return activeAnchor;
|
|
86
|
+
const observerRef = useRef(null);
|
|
87
|
+
const [activeAnchor, setActiveAnchor] = useState(() => []);
|
|
88
|
+
const stateRef = useRef(null);
|
|
89
|
+
const onChange = useEffectEvent((entries) => {
|
|
90
|
+
stateRef.current ??= { visible: /* @__PURE__ */ new Set() };
|
|
91
|
+
const state = stateRef.current;
|
|
92
|
+
for (const entry of entries) if (entry.isIntersecting) state.visible.add(entry.target.id);
|
|
93
|
+
else state.visible.delete(entry.target.id);
|
|
94
|
+
if (state.visible.size === 0) {
|
|
95
|
+
const viewTop = entries.length > 0 ? entries[0]?.rootBounds?.top ?? 0 : 0;
|
|
96
|
+
let fallback;
|
|
97
|
+
let min = -1;
|
|
98
|
+
for (const id of watch) {
|
|
99
|
+
const element = document.getElementById(id);
|
|
100
|
+
if (!element) continue;
|
|
101
|
+
const d = Math.abs(viewTop - element.getBoundingClientRect().top);
|
|
102
|
+
if (min === -1 || d < min) {
|
|
103
|
+
fallback = element;
|
|
104
|
+
min = d;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
setActiveAnchor(fallback ? [fallback.id] : []);
|
|
108
|
+
} else {
|
|
109
|
+
const items = watch.filter((item) => state.visible.has(item));
|
|
110
|
+
setActiveAnchor(single ? items.slice(0, 1) : items);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (observerRef.current) return;
|
|
115
|
+
observerRef.current = new IntersectionObserver(onChange, {
|
|
116
|
+
rootMargin: "0px",
|
|
117
|
+
threshold: .98
|
|
118
|
+
});
|
|
119
|
+
return () => {
|
|
120
|
+
observerRef.current?.disconnect();
|
|
121
|
+
observerRef.current = null;
|
|
122
|
+
};
|
|
123
|
+
}, []);
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
const observer = observerRef.current;
|
|
126
|
+
if (!observer) return;
|
|
127
|
+
const elements = watch.flatMap((heading) => document.getElementById(heading) ?? []);
|
|
128
|
+
for (const element of elements) observer.observe(element);
|
|
129
|
+
return () => {
|
|
130
|
+
for (const element of elements) observer.unobserve(element);
|
|
131
|
+
};
|
|
132
|
+
}, [watch]);
|
|
133
|
+
return activeAnchor;
|
|
144
134
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
useActiveAnchor,
|
|
150
|
-
useActiveAnchors
|
|
151
|
-
};
|
|
135
|
+
|
|
136
|
+
//#endregion
|
|
137
|
+
export { AnchorProvider, ScrollProvider, TOCItem, useActiveAnchor, useActiveAnchors };
|
|
138
|
+
//# sourceMappingURL=toc.js.map
|
package/dist/toc.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toc.js","names":["fallback: Element | undefined"],"sources":["../src/utils/merge-refs.ts","../src/toc.tsx"],"sourcesContent":["import type * as React from 'react';\n\nexport function mergeRefs<T>(...refs: (React.Ref<T> | undefined)[]): React.RefCallback<T> {\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref != null) {\n ref.current = value;\n }\n });\n };\n}\n","'use client';\nimport {\n type ComponentProps,\n createContext,\n type ReactNode,\n type RefObject,\n useContext,\n useEffect,\n useEffectEvent,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport scrollIntoView from 'scroll-into-view-if-needed';\nimport { mergeRefs } from '@/utils/merge-refs';\n\nexport interface TOCItemType {\n title: ReactNode;\n url: string;\n depth: number;\n}\n\nexport type TableOfContents = TOCItemType[];\n\nconst ActiveAnchorContext = createContext<string[]>([]);\n\nconst ScrollContext = createContext<RefObject<HTMLElement | null>>({\n current: null,\n});\n\n/**\n * The estimated active heading ID\n */\nexport function useActiveAnchor(): string | undefined {\n return useContext(ActiveAnchorContext)[0];\n}\n\n/**\n * The id of visible anchors\n */\nexport function useActiveAnchors(): string[] {\n return useContext(ActiveAnchorContext);\n}\n\nexport interface AnchorProviderProps {\n toc: TableOfContents;\n /**\n * Only accept one active item at most\n *\n * @defaultValue false\n */\n single?: boolean;\n children?: ReactNode;\n}\n\nexport interface ScrollProviderProps {\n /**\n * Scroll into the view of container when active\n */\n containerRef: RefObject<HTMLElement | null>;\n\n children?: ReactNode;\n}\n\nexport function ScrollProvider({ containerRef, children }: ScrollProviderProps) {\n return <ScrollContext.Provider value={containerRef}>{children}</ScrollContext.Provider>;\n}\n\nexport function AnchorProvider({ toc, single = false, children }: AnchorProviderProps) {\n const headings = useMemo(() => {\n return toc.map((item) => item.url.split('#')[1]);\n }, [toc]);\n\n return (\n <ActiveAnchorContext.Provider value={useAnchorObserver(headings, single)}>\n {children}\n </ActiveAnchorContext.Provider>\n );\n}\n\nexport interface TOCItemProps extends Omit<ComponentProps<'a'>, 'href'> {\n href: string;\n onActiveChange?: (v: boolean) => void;\n}\n\nexport function TOCItem({ ref, onActiveChange = () => null, ...props }: TOCItemProps) {\n const containerRef = useContext(ScrollContext);\n const anchorRef = useRef<HTMLAnchorElement>(null);\n const activeOrder = useActiveAnchors().indexOf(props.href.slice(1));\n const isActive = activeOrder !== -1;\n const shouldScroll = activeOrder === 0;\n const onActiveChangeEvent = useEffectEvent(onActiveChange);\n\n useLayoutEffect(() => {\n const anchor = anchorRef.current;\n const container = containerRef.current;\n\n if (container && anchor && shouldScroll)\n scrollIntoView(anchor, {\n behavior: 'smooth',\n block: 'center',\n inline: 'center',\n scrollMode: 'always',\n boundary: container,\n });\n }, [containerRef, shouldScroll]);\n\n useEffect(() => {\n return () => onActiveChangeEvent(isActive);\n }, [isActive]);\n\n return (\n <a ref={mergeRefs(anchorRef, ref)} data-active={isActive} {...props}>\n {props.children}\n </a>\n );\n}\n\n/**\n * Find the active heading of page\n *\n * It selects the top heading by default, and the last item when reached the bottom of page.\n *\n * @param watch - An array of element ids to watch\n * @param single - only one active item at most\n * @returns Active anchor\n */\nfunction useAnchorObserver(watch: string[], single: boolean): string[] {\n const observerRef = useRef<IntersectionObserver>(null);\n const [activeAnchor, setActiveAnchor] = useState<string[]>(() => []);\n const stateRef = useRef<{\n visible: Set<string>;\n }>(null);\n\n const onChange = useEffectEvent((entries: IntersectionObserverEntry[]) => {\n stateRef.current ??= {\n visible: new Set(),\n };\n const state = stateRef.current;\n\n for (const entry of entries) {\n if (entry.isIntersecting) {\n state.visible.add(entry.target.id);\n } else {\n state.visible.delete(entry.target.id);\n }\n }\n\n if (state.visible.size === 0) {\n const viewTop = entries.length > 0 ? (entries[0]?.rootBounds?.top ?? 0) : 0;\n let fallback: Element | undefined;\n let min = -1;\n\n for (const id of watch) {\n const element = document.getElementById(id);\n if (!element) continue;\n\n const d = Math.abs(viewTop - element.getBoundingClientRect().top);\n if (min === -1 || d < min) {\n fallback = element;\n min = d;\n }\n }\n\n setActiveAnchor(fallback ? [fallback.id] : []);\n } else {\n const items = watch.filter((item) => state.visible.has(item));\n setActiveAnchor(single ? items.slice(0, 1) : items);\n }\n });\n\n useEffect(() => {\n if (observerRef.current) return;\n observerRef.current = new IntersectionObserver(onChange, {\n rootMargin: '0px',\n threshold: 0.98,\n });\n\n return () => {\n observerRef.current?.disconnect();\n observerRef.current = null;\n };\n }, []);\n\n useEffect(() => {\n const observer = observerRef.current;\n if (!observer) return;\n const elements = watch.flatMap((heading) => document.getElementById(heading) ?? []);\n\n for (const element of elements) observer.observe(element);\n return () => {\n for (const element of elements) observer.unobserve(element);\n };\n }, [watch]);\n\n return activeAnchor;\n}\n"],"mappings":";;;;;;;AAEA,SAAgB,UAAa,GAAG,MAA0D;AACxF,SAAQ,UAAU;AAChB,OAAK,SAAS,QAAQ;AACpB,OAAI,OAAO,QAAQ,WACjB,KAAI,MAAM;YACD,OAAO,KAChB,KAAI,UAAU;IAEhB;;;;;;ACeN,MAAM,sBAAsB,cAAwB,EAAE,CAAC;AAEvD,MAAM,gBAAgB,cAA6C,EACjE,SAAS,MACV,CAAC;;;;AAKF,SAAgB,kBAAsC;AACpD,QAAO,WAAW,oBAAoB,CAAC;;;;;AAMzC,SAAgB,mBAA6B;AAC3C,QAAO,WAAW,oBAAoB;;AAuBxC,SAAgB,eAAe,EAAE,cAAc,YAAiC;AAC9E,QAAO,oBAAC,cAAc;EAAS,OAAO;EAAe;GAAkC;;AAGzF,SAAgB,eAAe,EAAE,KAAK,SAAS,OAAO,YAAiC;CACrF,MAAM,WAAW,cAAc;AAC7B,SAAO,IAAI,KAAK,SAAS,KAAK,IAAI,MAAM,IAAI,CAAC,GAAG;IAC/C,CAAC,IAAI,CAAC;AAET,QACE,oBAAC,oBAAoB;EAAS,OAAO,kBAAkB,UAAU,OAAO;EACrE;GAC4B;;AASnC,SAAgB,QAAQ,EAAE,KAAK,uBAAuB,MAAM,GAAG,SAAuB;CACpF,MAAM,eAAe,WAAW,cAAc;CAC9C,MAAM,YAAY,OAA0B,KAAK;CACjD,MAAM,cAAc,kBAAkB,CAAC,QAAQ,MAAM,KAAK,MAAM,EAAE,CAAC;CACnE,MAAM,WAAW,gBAAgB;CACjC,MAAM,eAAe,gBAAgB;CACrC,MAAM,sBAAsB,eAAe,eAAe;AAE1D,uBAAsB;EACpB,MAAM,SAAS,UAAU;EACzB,MAAM,YAAY,aAAa;AAE/B,MAAI,aAAa,UAAU,aACzB,gBAAe,QAAQ;GACrB,UAAU;GACV,OAAO;GACP,QAAQ;GACR,YAAY;GACZ,UAAU;GACX,CAAC;IACH,CAAC,cAAc,aAAa,CAAC;AAEhC,iBAAgB;AACd,eAAa,oBAAoB,SAAS;IACzC,CAAC,SAAS,CAAC;AAEd,QACE,oBAAC;EAAE,KAAK,UAAU,WAAW,IAAI;EAAE,eAAa;EAAU,GAAI;YAC3D,MAAM;GACL;;;;;;;;;;;AAaR,SAAS,kBAAkB,OAAiB,QAA2B;CACrE,MAAM,cAAc,OAA6B,KAAK;CACtD,MAAM,CAAC,cAAc,mBAAmB,eAAyB,EAAE,CAAC;CACpE,MAAM,WAAW,OAEd,KAAK;CAER,MAAM,WAAW,gBAAgB,YAAyC;AACxE,WAAS,YAAY,EACnB,yBAAS,IAAI,KAAK,EACnB;EACD,MAAM,QAAQ,SAAS;AAEvB,OAAK,MAAM,SAAS,QAClB,KAAI,MAAM,eACR,OAAM,QAAQ,IAAI,MAAM,OAAO,GAAG;MAElC,OAAM,QAAQ,OAAO,MAAM,OAAO,GAAG;AAIzC,MAAI,MAAM,QAAQ,SAAS,GAAG;GAC5B,MAAM,UAAU,QAAQ,SAAS,IAAK,QAAQ,IAAI,YAAY,OAAO,IAAK;GAC1E,IAAIA;GACJ,IAAI,MAAM;AAEV,QAAK,MAAM,MAAM,OAAO;IACtB,MAAM,UAAU,SAAS,eAAe,GAAG;AAC3C,QAAI,CAAC,QAAS;IAEd,MAAM,IAAI,KAAK,IAAI,UAAU,QAAQ,uBAAuB,CAAC,IAAI;AACjE,QAAI,QAAQ,MAAM,IAAI,KAAK;AACzB,gBAAW;AACX,WAAM;;;AAIV,mBAAgB,WAAW,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;SACzC;GACL,MAAM,QAAQ,MAAM,QAAQ,SAAS,MAAM,QAAQ,IAAI,KAAK,CAAC;AAC7D,mBAAgB,SAAS,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM;;GAErD;AAEF,iBAAgB;AACd,MAAI,YAAY,QAAS;AACzB,cAAY,UAAU,IAAI,qBAAqB,UAAU;GACvD,YAAY;GACZ,WAAW;GACZ,CAAC;AAEF,eAAa;AACX,eAAY,SAAS,YAAY;AACjC,eAAY,UAAU;;IAEvB,EAAE,CAAC;AAEN,iBAAgB;EACd,MAAM,WAAW,YAAY;AAC7B,MAAI,CAAC,SAAU;EACf,MAAM,WAAW,MAAM,SAAS,YAAY,SAAS,eAAe,QAAQ,IAAI,EAAE,CAAC;AAEnF,OAAK,MAAM,WAAW,SAAU,UAAS,QAAQ,QAAQ;AACzD,eAAa;AACX,QAAK,MAAM,WAAW,SAAU,UAAS,UAAU,QAAQ;;IAE5D,CAAC,MAAM,CAAC;AAEX,QAAO"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Pluggable } from "unified";
|
|
2
|
+
|
|
3
|
+
//#region src/content/mdx/util.d.ts
|
|
4
|
+
type Thenable<T> = T | PromiseLike<T>;
|
|
5
|
+
type ResolvePlugins = Thenable<Pluggable>[] | ((v: Pluggable[]) => Thenable<Pluggable>[]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { ResolvePlugins as t };
|
|
8
|
+
//# sourceMappingURL=util-CK2ykiif.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util-CK2ykiif.d.ts","names":[],"sources":["../src/content/mdx/util.ts"],"sourcesContent":[],"mappings":";;;KAEK,cAAc,IAAI,YAAY;KAEvB,cAAA,GAAiB,SAAS,oBAAoB,gBAAgB,SAAS"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/content/mdx/util.ts
|
|
2
|
+
async function resolvePlugins(def, options = []) {
|
|
3
|
+
const list = (await Promise.all(def(Array.isArray(options) ? options : []))).filter((v) => v !== false);
|
|
4
|
+
if (typeof options === "function") return Promise.all(options(list));
|
|
5
|
+
return list;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
export { resolvePlugins as t };
|
|
10
|
+
//# sourceMappingURL=util-s9piKHsk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util-s9piKHsk.js","names":[],"sources":["../src/content/mdx/util.ts"],"sourcesContent":["import type { Pluggable } from 'unified';\n\ntype Thenable<T> = T | PromiseLike<T>;\n\nexport type ResolvePlugins = Thenable<Pluggable>[] | ((v: Pluggable[]) => Thenable<Pluggable>[]);\n\nexport async function resolvePlugins(\n def: (v: Thenable<Pluggable>[]) => Thenable<Pluggable | false>[],\n options: ResolvePlugins = [],\n): Promise<Pluggable[]> {\n const list = (await Promise.all(def(Array.isArray(options) ? options : []))).filter(\n (v) => v !== false,\n );\n\n if (typeof options === 'function') {\n return Promise.all(options(list));\n }\n\n return list;\n}\n"],"mappings":";AAMA,eAAsB,eACpB,KACA,UAA0B,EAAE,EACN;CACtB,MAAM,QAAQ,MAAM,QAAQ,IAAI,IAAI,MAAM,QAAQ,QAAQ,GAAG,UAAU,EAAE,CAAC,CAAC,EAAE,QAC1E,MAAM,MAAM,MACd;AAED,KAAI,OAAO,YAAY,WACrB,QAAO,QAAQ,IAAI,QAAQ,KAAK,CAAC;AAGnC,QAAO"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//#region src/utils/use-effect-event.d.ts
|
|
1
2
|
type UseEffectEvent = <F extends (...params: never[]) => unknown>(callback: F) => F;
|
|
2
3
|
/**
|
|
3
4
|
* Polyfill for React.js 19.2 `useEffectEvent`.
|
|
@@ -5,5 +6,6 @@ type UseEffectEvent = <F extends (...params: never[]) => unknown>(callback: F) =
|
|
|
5
6
|
* @internal Don't use this, could be deleted anytime.
|
|
6
7
|
*/
|
|
7
8
|
declare const useEffectEvent: UseEffectEvent;
|
|
8
|
-
|
|
9
|
+
//#endregion
|
|
9
10
|
export { useEffectEvent };
|
|
11
|
+
//# sourceMappingURL=use-effect-event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-effect-event.d.ts","names":[],"sources":["../../src/utils/use-effect-event.ts"],"sourcesContent":[],"mappings":";KAGK,cAAA,yDAAuE,MAAM;;AAOlF;;;;cAAa,gBAAgB"}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
import "../chunk-U67V476Y.js";
|
|
1
|
+
'use client';
|
|
3
2
|
|
|
4
|
-
// src/utils/use-effect-event.ts
|
|
5
3
|
import * as React from "react";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
|
|
5
|
+
//#region src/utils/use-effect-event.ts
|
|
6
|
+
/**
|
|
7
|
+
* Polyfill for React.js 19.2 `useEffectEvent`.
|
|
8
|
+
*
|
|
9
|
+
* @internal Don't use this, could be deleted anytime.
|
|
10
|
+
*/
|
|
11
|
+
const useEffectEvent = "useEffectEvent" in React ? { ...React }.useEffectEvent : (callback) => {
|
|
12
|
+
const ref = React.useRef(callback);
|
|
13
|
+
ref.current = callback;
|
|
14
|
+
return React.useCallback(((...params) => ref.current(...params)), []);
|
|
16
15
|
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { useEffectEvent };
|
|
19
|
+
//# sourceMappingURL=use-effect-event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-effect-event.js","names":["useEffectEvent: UseEffectEvent"],"sources":["../../src/utils/use-effect-event.ts"],"sourcesContent":["'use client';\nimport * as React from 'react';\n\ntype UseEffectEvent = <F extends (...params: never[]) => unknown>(callback: F) => F;\n\n/**\n * Polyfill for React.js 19.2 `useEffectEvent`.\n *\n * @internal Don't use this, could be deleted anytime.\n */\nexport const useEffectEvent: UseEffectEvent =\n 'useEffectEvent' in React\n ? { ...React }.useEffectEvent\n : <F extends (...params: never[]) => unknown>(callback: F) => {\n const ref = React.useRef(callback);\n ref.current = callback;\n\n return React.useCallback(((...params) => ref.current(...params)) as F, []);\n };\n"],"mappings":";;;;;;;;;;AAUA,MAAaA,iBACX,oBAAoB,QAChB,EAAE,GAAG,OAAO,CAAC,kBAC+B,aAAgB;CAC1D,MAAM,MAAM,MAAM,OAAO,SAAS;AAClC,KAAI,UAAU;AAEd,QAAO,MAAM,cAAc,GAAG,WAAW,IAAI,QAAQ,GAAG,OAAO,GAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-media-query.d.ts","names":[],"sources":["../../src/utils/use-media-query.ts"],"sourcesContent":[],"mappings":";iBAEgB,aAAA"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import "../chunk-U67V476Y.js";
|
|
2
|
-
|
|
3
|
-
// src/utils/use-media-query.ts
|
|
4
1
|
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/use-media-query.ts
|
|
5
4
|
function useMediaQuery(query, disabled = false) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
const [isMatch, setMatch] = useState(null);
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
if (disabled) return;
|
|
8
|
+
const mediaQueryList = window.matchMedia(query);
|
|
9
|
+
const handleChange = () => {
|
|
10
|
+
setMatch(mediaQueryList.matches);
|
|
11
|
+
};
|
|
12
|
+
handleChange();
|
|
13
|
+
mediaQueryList.addEventListener("change", handleChange);
|
|
14
|
+
return () => {
|
|
15
|
+
mediaQueryList.removeEventListener("change", handleChange);
|
|
16
|
+
};
|
|
17
|
+
}, [disabled, query]);
|
|
18
|
+
return isMatch;
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { useMediaQuery };
|
|
23
|
+
//# sourceMappingURL=use-media-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-media-query.js","names":[],"sources":["../../src/utils/use-media-query.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nexport function useMediaQuery(query: string, disabled = false): boolean | null {\n const [isMatch, setMatch] = useState<boolean | null>(null);\n\n useEffect(() => {\n if (disabled) return;\n const mediaQueryList = window.matchMedia(query);\n\n const handleChange = () => {\n setMatch(mediaQueryList.matches);\n };\n handleChange();\n mediaQueryList.addEventListener('change', handleChange);\n return () => {\n mediaQueryList.removeEventListener('change', handleChange);\n };\n }, [disabled, query]);\n\n return isMatch;\n}\n"],"mappings":";;;AAEA,SAAgB,cAAc,OAAe,WAAW,OAAuB;CAC7E,MAAM,CAAC,SAAS,YAAY,SAAyB,KAAK;AAE1D,iBAAgB;AACd,MAAI,SAAU;EACd,MAAM,iBAAiB,OAAO,WAAW,MAAM;EAE/C,MAAM,qBAAqB;AACzB,YAAS,eAAe,QAAQ;;AAElC,gBAAc;AACd,iBAAe,iBAAiB,UAAU,aAAa;AACvD,eAAa;AACX,kBAAe,oBAAoB,UAAU,aAAa;;IAE3D,CAAC,UAAU,MAAM,CAAC;AAErB,QAAO"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
//#region src/utils/use-on-change.d.ts
|
|
1
2
|
/**
|
|
2
3
|
* @param value - state to watch
|
|
3
4
|
* @param onChange - when the state changed
|
|
4
5
|
* @param isUpdated - a function that determines if the state is updated
|
|
5
6
|
*/
|
|
6
7
|
declare function useOnChange<T>(value: T, onChange: (current: T, previous: T) => void, isUpdated?: (prev: T, current: T) => boolean): void;
|
|
7
|
-
|
|
8
|
+
//#endregion
|
|
8
9
|
export { useOnChange };
|
|
10
|
+
//# sourceMappingURL=use-on-change.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-on-change.d.ts","names":[],"sources":["../../src/utils/use-on-change.ts"],"sourcesContent":[],"mappings":";;AAeA;;;;AAGoB,iBAHJ,WAGI,CAAA,CAAA,CAAA,CAAA,KAAA,EAFX,CAEW,EAAA,QAAA,EAAA,CAAA,OAAA,EADE,CACF,EAAA,QAAA,EADe,CACf,EAAA,GAAA,IAAA,EAAA,SAAA,CAAA,EAAA,CAAA,IAAA,EAAA,CAAA,EAAA,OAAA,EAAY,CAAZ,EAAA,GAAA,OAAA,CAAA,EAAA,IAAA"}
|
|
@@ -1,7 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/use-on-change.ts
|
|
4
|
+
function isDifferent(a, b) {
|
|
5
|
+
if (Array.isArray(a) && Array.isArray(b)) return b.length !== a.length || a.some((v, i) => isDifferent(v, b[i]));
|
|
6
|
+
return a !== b;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* @param value - state to watch
|
|
10
|
+
* @param onChange - when the state changed
|
|
11
|
+
* @param isUpdated - a function that determines if the state is updated
|
|
12
|
+
*/
|
|
13
|
+
function useOnChange(value, onChange, isUpdated = isDifferent) {
|
|
14
|
+
const [prev, setPrev] = useState(value);
|
|
15
|
+
if (isUpdated(prev, value)) {
|
|
16
|
+
onChange(value, prev);
|
|
17
|
+
setPrev(value);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { useOnChange };
|
|
23
|
+
//# sourceMappingURL=use-on-change.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-on-change.js","names":[],"sources":["../../src/utils/use-on-change.ts"],"sourcesContent":["import { useState } from 'react';\n\nfunction isDifferent(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return b.length !== a.length || a.some((v, i) => isDifferent(v, b[i]));\n }\n\n return a !== b;\n}\n\n/**\n * @param value - state to watch\n * @param onChange - when the state changed\n * @param isUpdated - a function that determines if the state is updated\n */\nexport function useOnChange<T>(\n value: T,\n onChange: (current: T, previous: T) => void,\n isUpdated: (prev: T, current: T) => boolean = isDifferent,\n): void {\n const [prev, setPrev] = useState<T>(value);\n\n if (isUpdated(prev, value)) {\n onChange(value, prev);\n setPrev(value);\n }\n}\n"],"mappings":";;;AAEA,SAAS,YAAY,GAAY,GAAqB;AACpD,KAAI,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE,CACtC,QAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,YAAY,GAAG,EAAE,GAAG,CAAC;AAGxE,QAAO,MAAM;;;;;;;AAQf,SAAgB,YACd,OACA,UACA,YAA8C,aACxC;CACN,MAAM,CAAC,MAAM,WAAW,SAAY,MAAM;AAE1C,KAAI,UAAU,MAAM,MAAM,EAAE;AAC1B,WAAS,OAAO,KAAK;AACrB,UAAQ,MAAM"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
//#region src/page-tree/utils.ts
|
|
2
|
+
/**
|
|
3
|
+
* Flatten tree to an array of page nodes
|
|
4
|
+
*/
|
|
5
|
+
function flattenTree(nodes) {
|
|
6
|
+
const out = [];
|
|
7
|
+
for (const node of nodes) if (node.type === "folder") {
|
|
8
|
+
if (node.index) out.push(node.index);
|
|
9
|
+
out.push(...flattenTree(node.children));
|
|
10
|
+
} else if (node.type === "page") out.push(node);
|
|
11
|
+
return out;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Get neighbours of a page, useful for implementing "previous & next" buttons
|
|
15
|
+
*/
|
|
16
|
+
function findNeighbour(tree, url, options) {
|
|
17
|
+
const { separateRoot = true } = options ?? {};
|
|
18
|
+
const roots = separateRoot ? getPageTreeRoots(tree) : [tree];
|
|
19
|
+
if (tree.fallback) roots.push(tree.fallback);
|
|
20
|
+
for (const root of roots) {
|
|
21
|
+
const list = flattenTree(root.children);
|
|
22
|
+
const idx = list.findIndex((item) => item.url === url);
|
|
23
|
+
if (idx === -1) continue;
|
|
24
|
+
return {
|
|
25
|
+
previous: list[idx - 1],
|
|
26
|
+
next: list[idx + 1]
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
function getPageTreeRoots(pageTree) {
|
|
32
|
+
const result = pageTree.children.flatMap((child) => {
|
|
33
|
+
if (child.type !== "folder") return [];
|
|
34
|
+
const roots = getPageTreeRoots(child);
|
|
35
|
+
if (child.root) roots.push(child);
|
|
36
|
+
return roots;
|
|
37
|
+
});
|
|
38
|
+
if (!("type" in pageTree)) result.push(pageTree);
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get other item nodes that lives under the same parent.
|
|
43
|
+
*/
|
|
44
|
+
function getPageTreePeers(treeOrTrees, url) {
|
|
45
|
+
return findSiblings(treeOrTrees, url).filter((item) => item.type === "page");
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get other tree nodes that lives under the same parent.
|
|
49
|
+
*/
|
|
50
|
+
function findSiblings(treeOrTrees, url) {
|
|
51
|
+
if ("children" in treeOrTrees) {
|
|
52
|
+
const parent = findParent(treeOrTrees, url);
|
|
53
|
+
if (!parent) return [];
|
|
54
|
+
return parent.children.filter((item) => item.type !== "page" || item.url !== url);
|
|
55
|
+
}
|
|
56
|
+
for (const lang in treeOrTrees) {
|
|
57
|
+
const result = getPageTreePeers(treeOrTrees[lang], url);
|
|
58
|
+
if (result) return result;
|
|
59
|
+
}
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
function findParent(from, url) {
|
|
63
|
+
let result;
|
|
64
|
+
visit(from, (node, parent) => {
|
|
65
|
+
if ("type" in node && node.type === "page" && node.url === url) {
|
|
66
|
+
result = parent;
|
|
67
|
+
return "break";
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Search the path of a node in the tree matched by the matcher.
|
|
74
|
+
*
|
|
75
|
+
* @returns The path to the target node (from starting root), or null if the page doesn't exist
|
|
76
|
+
*/
|
|
77
|
+
function findPath(nodes, matcher, options = {}) {
|
|
78
|
+
const { includeSeparator = true } = options;
|
|
79
|
+
function run(nodes$1) {
|
|
80
|
+
let separator;
|
|
81
|
+
for (const node of nodes$1) {
|
|
82
|
+
if (matcher(node)) {
|
|
83
|
+
const items = [];
|
|
84
|
+
if (separator) items.push(separator);
|
|
85
|
+
items.push(node);
|
|
86
|
+
return items;
|
|
87
|
+
}
|
|
88
|
+
if (node.type === "separator" && includeSeparator) {
|
|
89
|
+
separator = node;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (node.type === "folder") {
|
|
93
|
+
const items = node.index && matcher(node.index) ? [node.index] : run(node.children);
|
|
94
|
+
if (items) {
|
|
95
|
+
items.unshift(node);
|
|
96
|
+
if (separator) items.unshift(separator);
|
|
97
|
+
return items;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return run(nodes) ?? null;
|
|
103
|
+
}
|
|
104
|
+
const VisitBreak = Symbol("VisitBreak");
|
|
105
|
+
/**
|
|
106
|
+
* Perform a depth-first search on page tree visiting every node.
|
|
107
|
+
*
|
|
108
|
+
* @param root - the root of page tree to visit.
|
|
109
|
+
* @param visitor - function to receive nodes, return `skip` to skip the children of current node, `break` to stop the search entirely.
|
|
110
|
+
*/
|
|
111
|
+
function visit(root, visitor) {
|
|
112
|
+
function onNode(node, parent) {
|
|
113
|
+
const result = visitor(node, parent);
|
|
114
|
+
switch (result) {
|
|
115
|
+
case "skip": return node;
|
|
116
|
+
case "break": throw VisitBreak;
|
|
117
|
+
default: if (result) node = result;
|
|
118
|
+
}
|
|
119
|
+
if ("index" in node && node.index) node.index = onNode(node.index, node);
|
|
120
|
+
if ("fallback" in node && node.fallback) node.fallback = onNode(node.fallback, node);
|
|
121
|
+
if ("children" in node) for (let i = 0; i < node.children.length; i++) node.children[i] = onNode(node.children[i], node);
|
|
122
|
+
return node;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
return onNode(root);
|
|
126
|
+
} catch (e) {
|
|
127
|
+
if (e === VisitBreak) return root;
|
|
128
|
+
throw e;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
//#endregion
|
|
133
|
+
export { flattenTree as a, visit as c, findSiblings as i, findParent as n, getPageTreePeers as o, findPath as r, getPageTreeRoots as s, findNeighbour as t };
|
|
134
|
+
//# sourceMappingURL=utils-DUvi2WkD.js.map
|