zudoku 0.35.6 → 0.37.0
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/README.md +1 -1
- package/dist/app/entry.server.js +5 -1
- package/dist/app/entry.server.js.map +1 -1
- package/dist/config/validators/common.d.ts +428 -428
- package/dist/config/validators/common.js +12 -7
- package/dist/config/validators/common.js.map +1 -1
- package/dist/config/validators/validate.d.ts +158 -158
- package/dist/lib/components/InlineCode.d.ts +2 -1
- package/dist/lib/components/InlineCode.js +1 -1
- package/dist/lib/components/InlineCode.js.map +1 -1
- package/dist/lib/components/Layout.js +3 -14
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/components/MobileTopNavigation.js +1 -1
- package/dist/lib/components/MobileTopNavigation.js.map +1 -1
- package/dist/lib/components/TopNavigation.d.ts +2 -2
- package/dist/lib/components/TopNavigation.js +9 -12
- package/dist/lib/components/TopNavigation.js.map +1 -1
- package/dist/lib/components/Zudoku.js +3 -1
- package/dist/lib/components/Zudoku.js.map +1 -1
- package/dist/lib/components/cache.d.ts +7 -0
- package/dist/lib/components/cache.js +7 -0
- package/dist/lib/components/cache.js.map +1 -1
- package/dist/lib/components/context/ViewportAnchorContext.js +3 -6
- package/dist/lib/components/context/ViewportAnchorContext.js.map +1 -1
- package/dist/lib/components/context/ZudokuContext.d.ts +2 -2
- package/dist/lib/components/context/ZudokuContext.js +13 -7
- package/dist/lib/components/context/ZudokuContext.js.map +1 -1
- package/dist/lib/components/navigation/SidebarCategory.d.ts +2 -2
- package/dist/lib/components/navigation/SidebarCategory.js +10 -6
- package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
- package/dist/lib/components/navigation/SidebarItem.js +2 -2
- package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
- package/dist/lib/components/navigation/SidebarWrapper.js +1 -1
- package/dist/lib/components/navigation/SidebarWrapper.js.map +1 -1
- package/dist/lib/core/ZudokuContext.d.ts +8 -6
- package/dist/lib/core/ZudokuContext.js +4 -2
- package/dist/lib/core/ZudokuContext.js.map +1 -1
- package/dist/lib/core/plugins.d.ts +3 -3
- package/dist/lib/hooks/useEvent.test.js +1 -1
- package/dist/lib/hooks/useEvent.test.js.map +1 -1
- package/dist/lib/oas/graphql/index.d.ts +13 -2
- package/dist/lib/oas/graphql/index.js +59 -39
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +19 -5
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/ParamInfos.js +12 -4
- package/dist/lib/plugins/openapi/ParamInfos.js.map +1 -1
- package/dist/lib/plugins/openapi/ParameterListItem.js +1 -1
- package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +2 -2
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.d.ts +1 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.js +2 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.d.ts +4 -4
- package/dist/lib/plugins/openapi/graphql/gql.js +3 -3
- package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/graphql.d.ts +33 -44
- package/dist/lib/plugins/openapi/graphql/graphql.js +19 -29
- package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
- package/dist/lib/plugins/openapi/index.d.ts +5 -10
- package/dist/lib/plugins/openapi/index.js +29 -60
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/interfaces.d.ts +3 -1
- package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js +3 -3
- package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js.map +1 -1
- package/dist/lib/plugins/openapi/schema/SchemaView.js +13 -6
- package/dist/lib/plugins/openapi/schema/SchemaView.js.map +1 -1
- package/dist/lib/plugins/openapi/util/createSidebarCategory.js +5 -7
- package/dist/lib/plugins/openapi/util/createSidebarCategory.js.map +1 -1
- package/dist/lib/ui/Badge.d.ts +1 -1
- package/dist/lib/ui/Button.d.ts +1 -1
- package/dist/lib/ui/Button.js +1 -1
- package/dist/lib/ui/Button.js.map +1 -1
- package/dist/lib/ui/Command.d.ts +6 -6
- package/dist/lib/util/joinPath.d.ts +3 -0
- package/dist/lib/util/joinPath.js +3 -0
- package/dist/lib/util/joinPath.js.map +1 -1
- package/dist/lib/util/traverse.js +2 -2
- package/dist/lib/util/traverse.js.map +1 -1
- package/dist/lib/util/useScrollToAnchor.js +2 -0
- package/dist/lib/util/useScrollToAnchor.js.map +1 -1
- package/dist/vite/api/schema-codegen.js +19 -4
- package/dist/vite/api/schema-codegen.js.map +1 -1
- package/dist/vite/api/schema-codegen.test.js +61 -0
- package/dist/vite/api/schema-codegen.test.js.map +1 -1
- package/dist/vite/config.js +1 -1
- package/dist/vite/config.js.map +1 -1
- package/dist/vite/plugin-api.js +4 -12
- package/dist/vite/plugin-api.js.map +1 -1
- package/dist/vite/plugin-docs.d.ts +1 -1
- package/dist/vite/plugin-docs.js +18 -1
- package/dist/vite/plugin-docs.js.map +1 -1
- package/lib/{AuthenticationPlugin-4ip08maU.js → AuthenticationPlugin-Cij2tPWa.js} +2 -2
- package/lib/{AuthenticationPlugin-4ip08maU.js.map → AuthenticationPlugin-Cij2tPWa.js.map} +1 -1
- package/lib/{Spinner-C6n4eOvh.js → Button-Fp19CMUr.js} +15 -18
- package/lib/Button-Fp19CMUr.js.map +1 -0
- package/lib/{Markdown-C0eXdzGn.js → Markdown-DT5Rrq8_.js} +3526 -3264
- package/lib/Markdown-DT5Rrq8_.js.map +1 -0
- package/lib/{MdxPage-BKkG1cm1.js → MdxPage-D2rD1vC4.js} +3 -3
- package/lib/{MdxPage-BKkG1cm1.js.map → MdxPage-D2rD1vC4.js.map} +1 -1
- package/lib/{OasProvider-CwhKwrwl.js → OasProvider-DdEBf2qS.js} +3 -3
- package/lib/{OasProvider-CwhKwrwl.js.map → OasProvider-DdEBf2qS.js.map} +1 -1
- package/lib/{OperationList-DGYoFitT.js → OperationList-DT4-gm_S.js} +1122 -1093
- package/lib/OperationList-DT4-gm_S.js.map +1 -0
- package/lib/{Select-FAYHOYTy.js → Select-z1Lwl0-J.js} +3 -3
- package/lib/{Select-FAYHOYTy.js.map → Select-z1Lwl0-J.js.map} +1 -1
- package/lib/{SlotletProvider-BJC58V32.js → SlotletProvider-D8OBnr77.js} +2 -2
- package/lib/{SlotletProvider-BJC58V32.js.map → SlotletProvider-D8OBnr77.js.map} +1 -1
- package/lib/Spinner-CE68iCm0.js +7 -0
- package/lib/Spinner-CE68iCm0.js.map +1 -0
- package/lib/{circular-v7K6lDDh.js → circular-ByJI6Mci.js} +4887 -4419
- package/lib/circular-ByJI6Mci.js.map +1 -0
- package/lib/{createServer-CbL1Uh2Q.js → createServer-DjgKDpGV.js} +3301 -3747
- package/lib/createServer-DjgKDpGV.js.map +1 -0
- package/lib/{hook-CfCFKZ-2.js → hook-DzQC8PzJ.js} +78 -73
- package/lib/hook-DzQC8PzJ.js.map +1 -0
- package/lib/{index-Dm1QJHVl.js → index-DdQSV2RF.js} +593 -633
- package/lib/index-DdQSV2RF.js.map +1 -0
- package/lib/{useQuery-CQUwWR9i.js → joinUrl-BjDooT-T.js} +240 -223
- package/lib/joinUrl-BjDooT-T.js.map +1 -0
- package/lib/{mutation-B81DztCT.js → mutation-_Z5C2wFZ.js} +2 -2
- package/lib/{mutation-B81DztCT.js.map → mutation-_Z5C2wFZ.js.map} +1 -1
- package/lib/post-processors/traverse.js +2 -2
- package/lib/post-processors/traverse.js.map +1 -1
- package/lib/ui/ActionButton.js +11 -10
- package/lib/ui/ActionButton.js.map +1 -1
- package/lib/ui/Button.js +1 -1
- package/lib/ui/Button.js.map +1 -1
- package/lib/zudoku.auth-auth0.js +1 -1
- package/lib/zudoku.auth-clerk.js +2 -2
- package/lib/zudoku.auth-openid.js +3 -3
- package/lib/zudoku.components.js +438 -444
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.hooks.js +1 -1
- package/lib/zudoku.plugin-api-catalog.js +3 -3
- package/lib/zudoku.plugin-api-keys.js +4 -4
- package/lib/zudoku.plugin-custom-pages.js +1 -1
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +5 -6
- package/lib/zudoku.plugin-openapi.js.map +1 -1
- package/lib/zudoku.plugin-search-pagefind.js +15 -16
- package/lib/zudoku.plugin-search-pagefind.js.map +1 -1
- package/lib/zudoku.plugins.js.map +1 -1
- package/package.json +3 -1
- package/src/app/entry.server.tsx +7 -1
- package/src/lib/components/InlineCode.tsx +3 -1
- package/src/lib/components/Layout.tsx +3 -16
- package/src/lib/components/MobileTopNavigation.tsx +1 -1
- package/src/lib/components/TopNavigation.tsx +12 -16
- package/src/lib/components/Zudoku.tsx +5 -1
- package/src/lib/components/cache.ts +8 -0
- package/src/lib/components/context/ViewportAnchorContext.tsx +3 -6
- package/src/lib/components/context/ZudokuContext.ts +17 -8
- package/src/lib/components/navigation/SidebarCategory.tsx +15 -12
- package/src/lib/components/navigation/SidebarItem.tsx +2 -2
- package/src/lib/components/navigation/SidebarWrapper.tsx +2 -2
- package/src/lib/core/ZudokuContext.ts +11 -8
- package/src/lib/core/plugins.ts +4 -4
- package/src/lib/hooks/useEvent.test.tsx +1 -1
- package/src/lib/oas/graphql/index.ts +104 -64
- package/src/lib/plugins/openapi/OperationList.tsx +30 -36
- package/src/lib/plugins/openapi/OperationListItem.tsx +1 -1
- package/src/lib/plugins/openapi/ParamInfos.tsx +27 -4
- package/src/lib/plugins/openapi/ParameterListItem.tsx +5 -1
- package/src/lib/plugins/openapi/Sidecar.tsx +2 -2
- package/src/lib/plugins/openapi/client/useCreateQuery.ts +2 -1
- package/src/lib/plugins/openapi/graphql/gql.ts +17 -17
- package/src/lib/plugins/openapi/graphql/graphql.ts +57 -75
- package/src/lib/plugins/openapi/index.tsx +40 -84
- package/src/lib/plugins/openapi/interfaces.ts +4 -1
- package/src/lib/plugins/openapi/schema/SchemaPropertyItem.tsx +5 -2
- package/src/lib/plugins/openapi/schema/SchemaView.tsx +48 -35
- package/src/lib/plugins/openapi/util/createSidebarCategory.tsx +5 -7
- package/src/lib/ui/Button.tsx +1 -1
- package/src/lib/util/joinPath.tsx +3 -0
- package/src/lib/util/traverse.ts +2 -2
- package/src/lib/util/useScrollToAnchor.ts +2 -0
- package/lib/Markdown-C0eXdzGn.js.map +0 -1
- package/lib/OperationList-DGYoFitT.js.map +0 -1
- package/lib/Spinner-C6n4eOvh.js.map +0 -1
- package/lib/circular-v7K6lDDh.js.map +0 -1
- package/lib/createServer-CbL1Uh2Q.js.map +0 -1
- package/lib/hook-CfCFKZ-2.js.map +0 -1
- package/lib/index-Dm1QJHVl.js.map +0 -1
- package/lib/joinUrl-10po2Jdj.js +0 -20
- package/lib/joinUrl-10po2Jdj.js.map +0 -1
- package/lib/useQuery-CQUwWR9i.js.map +0 -1
package/lib/zudoku.hooks.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z as f } from "./index-DwT-v3zK.js";
|
|
2
2
|
import { useState as m, useEffect as i } from "react";
|
|
3
|
-
import { a } from "./hook-
|
|
3
|
+
import { a } from "./hook-DzQC8PzJ.js";
|
|
4
4
|
function d(e, t) {
|
|
5
5
|
const s = a(), [n, o] = m();
|
|
6
6
|
return i(() => s.addEventListener(e, (...u) => {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import { s as h } from "./index-LNp6rxyU.js";
|
|
3
3
|
import { d as b, m as x } from "./chunk-HA7DTUK3-ZGg2W6yV.js";
|
|
4
|
-
import { j as d } from "./joinUrl-
|
|
5
|
-
import { u as j, b as y } from "./hook-
|
|
4
|
+
import { j as d } from "./joinUrl-BjDooT-T.js";
|
|
5
|
+
import { u as j, b as y } from "./hook-DzQC8PzJ.js";
|
|
6
6
|
import { H as v } from "./index.esm-CltAN0Tf.js";
|
|
7
7
|
import { Link as N } from "./zudoku.components.js";
|
|
8
|
-
import { H as S, M as w } from "./Markdown-
|
|
8
|
+
import { H as S, M as w } from "./Markdown-DT5Rrq8_.js";
|
|
9
9
|
const H = ({
|
|
10
10
|
items: s,
|
|
11
11
|
filterCatalogItems: l = (n) => n,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import { RotateCwIcon as j, TrashIcon as v, EyeOffIcon as w, EyeIcon as K, CheckIcon as b, CopyIcon as k, FileKey2Icon as N } from "lucide-react";
|
|
3
|
-
import { D as I, S as x, R as S } from "./SlotletProvider-
|
|
3
|
+
import { D as I, S as x, R as S } from "./SlotletProvider-D8OBnr77.js";
|
|
4
4
|
import { i as c } from "./invariant-Caa8-XvF.js";
|
|
5
|
-
import { u as h } from "./
|
|
6
|
-
import { u as d, S as A, a as C, b as E, c as P, d as D, e as p } from "./Select-
|
|
5
|
+
import { u as h } from "./joinUrl-BjDooT-T.js";
|
|
6
|
+
import { u as d, S as A, a as C, b as E, c as P, d as D, e as p } from "./Select-z1Lwl0-J.js";
|
|
7
7
|
import { a as q } from "./index.esm--gIChbWs.js";
|
|
8
8
|
import { a as R, L as u, O } from "./chunk-HA7DTUK3-ZGg2W6yV.js";
|
|
9
|
-
import { a as g, e as z, b as F } from "./hook-
|
|
9
|
+
import { a as g, e as z, b as F } from "./hook-DzQC8PzJ.js";
|
|
10
10
|
import { Button as l } from "./ui/Button.js";
|
|
11
11
|
import { Input as T } from "./ui/Input.js";
|
|
12
12
|
import { useState as y } from "react";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { j as o } from "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import a from "react";
|
|
3
|
-
import { P as n } from "./Markdown-
|
|
3
|
+
import { P as n } from "./Markdown-DT5Rrq8_.js";
|
|
4
4
|
import { c } from "./cn-qaFjX9_3.js";
|
|
5
5
|
import { u as p } from "./useExposedProps-BslIn-FE.js";
|
|
6
6
|
const u = ({
|
|
@@ -53,7 +53,7 @@ const P = (e) => ({
|
|
|
53
53
|
const u = {
|
|
54
54
|
path: r,
|
|
55
55
|
lazy: async () => {
|
|
56
|
-
const { MdxPage: p } = await import("./MdxPage-
|
|
56
|
+
const { MdxPage: p } = await import("./MdxPage-D2rD1vC4.js"), { default: f, ...l } = await i();
|
|
57
57
|
return {
|
|
58
58
|
element: /* @__PURE__ */ d.jsx(
|
|
59
59
|
p,
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import "./jsx-runtime-CYK1ROHF.js";
|
|
2
|
-
import "./index-LNp6rxyU.js";
|
|
3
2
|
import "lucide-react";
|
|
4
3
|
import "./chunk-HA7DTUK3-ZGg2W6yV.js";
|
|
5
|
-
import "./hook-
|
|
4
|
+
import "./hook-DzQC8PzJ.js";
|
|
6
5
|
import "./ui/Button.js";
|
|
7
|
-
import "./joinUrl-
|
|
8
|
-
import { U as
|
|
6
|
+
import "./joinUrl-BjDooT-T.js";
|
|
7
|
+
import { U as e, o as n } from "./index-DdQSV2RF.js";
|
|
9
8
|
export {
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
e as UNTAGGED_PATH,
|
|
10
|
+
n as openApiPlugin
|
|
12
11
|
};
|
|
13
12
|
//# sourceMappingURL=zudoku.plugin-openapi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import { C as x } from "./ClientOnly-E7hGysn1.js";
|
|
3
3
|
import { VisuallyHidden as y } from "@radix-ui/react-visually-hidden";
|
|
4
|
-
import { d as f, k as j } from "./
|
|
5
|
-
import { useCallback as
|
|
6
|
-
import { C
|
|
7
|
-
import { b as
|
|
8
|
-
import { j as L } from "./joinUrl-10po2Jdj.js";
|
|
4
|
+
import { d as f, k as j, j as S } from "./joinUrl-BjDooT-T.js";
|
|
5
|
+
import { useCallback as b, useState as k } from "react";
|
|
6
|
+
import { C, a as u, b as h, c as N, d as v, e as w, f as _ } from "./Callout-B2vsR09t.js";
|
|
7
|
+
import { b as L } from "./Dialog-sbgekbjb.js";
|
|
9
8
|
import { FileTextIcon as F } from "lucide-react";
|
|
10
9
|
import { a as T, L as g } from "./chunk-HA7DTUK3-ZGg2W6yV.js";
|
|
11
10
|
const q = async (r, o) => {
|
|
@@ -45,14 +44,14 @@ const $ = (r, o) => {
|
|
|
45
44
|
onClose: n,
|
|
46
45
|
maxSubResults: i = 4
|
|
47
46
|
}) => {
|
|
48
|
-
const l = T(), a =
|
|
47
|
+
const l = T(), a = b(
|
|
49
48
|
(t) => {
|
|
50
49
|
const c = t.replace(".html", "");
|
|
51
50
|
return r && c.startsWith(r) ? c.slice(r.length) : c;
|
|
52
51
|
},
|
|
53
52
|
[r]
|
|
54
53
|
);
|
|
55
|
-
return /* @__PURE__ */ e.jsxs(
|
|
54
|
+
return /* @__PURE__ */ e.jsxs(C, { className: "max-h-[450px]", children: [
|
|
56
55
|
s && o.length > 0 && /* @__PURE__ */ e.jsx(
|
|
57
56
|
u,
|
|
58
57
|
{
|
|
@@ -117,7 +116,7 @@ const $ = (r, o) => {
|
|
|
117
116
|
termSaturation: 1.2
|
|
118
117
|
}, E = (r) => import(
|
|
119
118
|
/* @vite-ignore */
|
|
120
|
-
|
|
119
|
+
S(r, "/pagefind/pagefind.js")
|
|
121
120
|
), I = (r) => {
|
|
122
121
|
const { data: o, ...s } = f({
|
|
123
122
|
queryKey: ["pagefind", r.ranking],
|
|
@@ -142,7 +141,7 @@ const $ = (r, o) => {
|
|
|
142
141
|
onClose: o,
|
|
143
142
|
options: s
|
|
144
143
|
}) => {
|
|
145
|
-
const { pagefind: n, error: i, isError: l } = I(s), [a, t] =
|
|
144
|
+
const { pagefind: n, error: i, isError: l } = I(s), [a, t] = k(""), { data: c } = f({
|
|
146
145
|
queryKey: ["pagefind-search", a],
|
|
147
146
|
queryFn: async () => {
|
|
148
147
|
const m = await (n == null ? void 0 : n.search(a));
|
|
@@ -152,16 +151,16 @@ const $ = (r, o) => {
|
|
|
152
151
|
enabled: !!n && !!a
|
|
153
152
|
});
|
|
154
153
|
return /* @__PURE__ */ e.jsxs(
|
|
155
|
-
|
|
154
|
+
N,
|
|
156
155
|
{
|
|
157
156
|
command: { shouldFilter: !1 },
|
|
158
157
|
content: { className: "max-w-[750px]" },
|
|
159
158
|
open: r,
|
|
160
159
|
onOpenChange: o,
|
|
161
160
|
children: [
|
|
162
|
-
/* @__PURE__ */ e.jsx(y, { children: /* @__PURE__ */ e.jsx(
|
|
161
|
+
/* @__PURE__ */ e.jsx(y, { children: /* @__PURE__ */ e.jsx(L, { children: "Search" }) }),
|
|
163
162
|
/* @__PURE__ */ e.jsx(
|
|
164
|
-
|
|
163
|
+
v,
|
|
165
164
|
{
|
|
166
165
|
placeholder: "Search...",
|
|
167
166
|
value: a,
|
|
@@ -169,8 +168,8 @@ const $ = (r, o) => {
|
|
|
169
168
|
disabled: l
|
|
170
169
|
}
|
|
171
170
|
),
|
|
172
|
-
/* @__PURE__ */ e.jsx(
|
|
173
|
-
l ? /* @__PURE__ */ e.jsx("div", { className: "p-4 text-sm", children: i.message === "NOT_BUILT_YET" ? /* @__PURE__ */ e.jsxs(
|
|
171
|
+
/* @__PURE__ */ e.jsx(w, { children: a ? "No results found." : "Start typing to search" }),
|
|
172
|
+
l ? /* @__PURE__ */ e.jsx("div", { className: "p-4 text-sm", children: i.message === "NOT_BUILT_YET" ? /* @__PURE__ */ e.jsxs(_, { type: "info", children: [
|
|
174
173
|
"Search is currently not available in development mode by default.",
|
|
175
174
|
/* @__PURE__ */ e.jsx("br", {}),
|
|
176
175
|
"To still use search in development, run ",
|
|
@@ -195,10 +194,10 @@ const $ = (r, o) => {
|
|
|
195
194
|
]
|
|
196
195
|
}
|
|
197
196
|
);
|
|
198
|
-
},
|
|
197
|
+
}, M = (r) => ({
|
|
199
198
|
renderSearch: ({ isOpen: o, onClose: s }) => /* @__PURE__ */ e.jsx(x, { children: /* @__PURE__ */ e.jsx(P, { isOpen: o, onClose: s, options: r }) })
|
|
200
199
|
});
|
|
201
200
|
export {
|
|
202
|
-
|
|
201
|
+
M as pagefindSearchPlugin
|
|
203
202
|
};
|
|
204
203
|
//# sourceMappingURL=zudoku.plugin-search-pagefind.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zudoku.plugin-search-pagefind.js","sources":["../src/lib/plugins/search-pagefind/get-results.tsx","../src/lib/plugins/search-pagefind/ResultList.tsx","../src/lib/plugins/search-pagefind/PagefindSearch.tsx","../src/lib/plugins/search-pagefind/index.tsx"],"sourcesContent":["import type { PagefindOptions } from \"./index.js\";\nimport type { PagefindSearchFragment, PagefindSearchResults } from \"./types.js\";\n\nexport const getResults = async (\n search: PagefindSearchResults,\n options: PagefindOptions,\n) => {\n const maxResults = options.maxResults ?? 10;\n const transformFn = options.transformResults ?? (() => true);\n\n const transformedResults: PagefindSearchFragment[] = [];\n\n const generator = searchResultGenerator(search, transformFn);\n\n for await (const result of generator) {\n transformedResults.push(result);\n if (transformedResults.length >= maxResults) break;\n }\n\n return transformedResults;\n};\n\nasync function* searchResultGenerator(\n search: PagefindSearchResults,\n transformFn: NonNullable<PagefindOptions[\"transformResults\"]>,\n) {\n const batchSize = 5;\n let processedCount = 0;\n\n while (processedCount < search.results.length) {\n const batch = search.results.slice(\n processedCount,\n processedCount + batchSize,\n );\n processedCount += batch.length;\n\n const batchData = await Promise.all(batch.map((result) => result.data()));\n\n for (const result of batchData) {\n const transformed = transformFn(result);\n\n if (transformed === false) {\n // Skip this result\n continue;\n } else if (transformed === true || transformed == null) {\n // Keep the original result\n yield result;\n } else {\n // Return the transformed result\n yield transformed;\n }\n }\n }\n}\n","import { FileTextIcon } from \"lucide-react\";\nimport { useCallback } from \"react\";\nimport { Link, useNavigate } from \"react-router\";\nimport { CommandGroup, CommandItem, CommandList } from \"zudoku/ui/Command.js\";\nimport {\n type PagefindSearchFragment,\n type PagefindSubResult,\n} from \"./types.js\";\n\nconst sortSubResults = (a: PagefindSubResult, b: PagefindSubResult) => {\n const aScore = a.weighted_locations.reduce(\n (sum, loc) => sum + loc.balanced_score,\n 0,\n );\n const bScore = b.weighted_locations.reduce(\n (sum, loc) => sum + loc.balanced_score,\n 0,\n );\n return bScore - aScore;\n};\n\nconst hoverClassname = `cursor-pointer border border-transparent data-[selected=true]:border-border`;\n\nexport const ResultList = ({\n basePath,\n searchResults,\n searchTerm,\n onClose,\n maxSubResults = 4,\n}: {\n basePath?: string;\n searchResults: PagefindSearchFragment[];\n searchTerm: string;\n onClose: () => void;\n maxSubResults?: number;\n}) => {\n const navigate = useNavigate();\n\n const cleanResultUrl = useCallback(\n (url: string) => {\n const clean = url.replace(\".html\", \"\");\n return basePath && clean.startsWith(basePath)\n ? clean.slice(basePath.length)\n : clean;\n },\n [basePath],\n );\n\n return (\n <CommandList className=\"max-h-[450px]\">\n {searchTerm && searchResults.length > 0 && (\n <CommandGroup\n className=\"text-sm text-muted-foreground\"\n heading={`${searchResults.length} results for \"${searchTerm}\"`}\n />\n )}\n {searchResults.map((result) => (\n <CommandGroup\n key={[result.meta.title ?? result.excerpt, result.url].join(\"-\")}\n >\n <CommandItem\n asChild\n value={`${result.meta.title}-${result.url}`}\n className={hoverClassname}\n onSelect={() => {\n void navigate(cleanResultUrl(result.url));\n onClose();\n }}\n >\n <Link to={cleanResultUrl(result.url)}>\n <FileTextIcon size={20} className=\"text-muted-foreground\" />\n {result.meta.title}\n </Link>\n </CommandItem>\n {result.sub_results\n .sort(sortSubResults)\n .slice(0, maxSubResults)\n .map((subResult) => (\n <CommandItem\n asChild\n key={`${result.meta.title}-${subResult.url}`}\n value={`${result.meta.title}-${subResult.url}`}\n className={hoverClassname}\n onSelect={() => {\n void navigate(cleanResultUrl(subResult.url));\n onClose();\n }}\n >\n <Link to={cleanResultUrl(subResult.url)} onClick={onClose}>\n <div className=\"flex flex-col items-start gap-2 ms-2.5 ps-5 border-l border-muted-foreground/50\">\n <span className=\"font-bold\">{subResult.title}</span>\n <span\n className=\"text-[13px] [&_mark]:bg-primary [&_mark]:text-primary-foreground\"\n dangerouslySetInnerHTML={{ __html: subResult.excerpt }}\n />\n </div>\n </Link>\n </CommandItem>\n ))}\n </CommandGroup>\n ))}\n </CommandList>\n );\n};\n","import { VisuallyHidden } from \"@radix-ui/react-visually-hidden\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useState } from \"react\";\nimport { Callout } from \"zudoku/ui/Callout.js\";\nimport {\n CommandDialog,\n CommandEmpty,\n CommandInput,\n} from \"zudoku/ui/Command.js\";\nimport { DialogTitle } from \"zudoku/ui/Dialog.js\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport { getResults } from \"./get-results.js\";\nimport type { PagefindOptions } from \"./index.js\";\nimport { ResultList } from \"./ResultList.js\";\nimport type { Pagefind } from \"./types.js\";\n\nconst DEFAULT_RANKING = {\n // Slightly lower than default because API docs tend to have repetitive terms (parameter names, HTTP methods, etc.)\n termFrequency: 0.8,\n // Lower than default because API documentation pages tend to be longer due to comprehensive endpoint documentation\n pageLength: 0.6,\n // Slightly higher than default because in technical documentation, exact matches should be prioritized\n termSimilarity: 1.2,\n // Slightly lower than default because API docs might have legitimate repetition of terms\n termSaturation: 1.2,\n};\n\nconst importPagefind = (basePath?: string): Promise<Pagefind> =>\n import.meta.env.DEV\n ? // @ts-expect-error TypeScript can't resolve the import\n import(/* @vite-ignore */ \"/pagefind/pagefind.js\")\n : import(/* @vite-ignore */ joinUrl(basePath, \"/pagefind/pagefind.js\"));\n\nconst usePagefind = (options: PagefindOptions) => {\n const { data: pagefind, ...result } = useQuery<Pagefind>({\n queryKey: [\"pagefind\", options.ranking],\n retry: false,\n queryFn: async () => {\n const pagefind = await importPagefind(options.basePath);\n await pagefind.init();\n await pagefind.options({\n ranking: {\n termFrequency:\n options.ranking?.termFrequency ?? DEFAULT_RANKING.termFrequency,\n pageLength: options.ranking?.pageLength ?? DEFAULT_RANKING.pageLength,\n termSimilarity:\n options.ranking?.termSimilarity ?? DEFAULT_RANKING.termSimilarity,\n termSaturation:\n options.ranking?.termSaturation ?? DEFAULT_RANKING.termSaturation,\n },\n });\n\n return pagefind;\n },\n enabled: typeof window !== \"undefined\",\n });\n\n if (result.isError) {\n // eslint-disable-next-line no-console\n console.error(result.error);\n }\n\n return { ...result, pagefind };\n};\n\nexport const PagefindSearch = ({\n isOpen,\n onClose,\n options,\n}: {\n isOpen: boolean;\n onClose: () => void;\n options: PagefindOptions;\n}) => {\n const { pagefind, error, isError } = usePagefind(options);\n const [searchTerm, setSearchTerm] = useState(\"\");\n\n const { data: searchResults } = useQuery({\n queryKey: [\"pagefind-search\", searchTerm],\n queryFn: async () => {\n const search = await pagefind?.search(searchTerm);\n if (!search) return [];\n return getResults(search, options);\n },\n placeholderData: keepPreviousData,\n enabled: !!pagefind && !!searchTerm,\n });\n\n return (\n <CommandDialog\n command={{ shouldFilter: false }}\n content={{ className: \"max-w-[750px]\" }}\n open={isOpen}\n onOpenChange={onClose}\n >\n <VisuallyHidden>\n <DialogTitle>Search</DialogTitle>\n </VisuallyHidden>\n <CommandInput\n placeholder=\"Search...\"\n value={searchTerm}\n onValueChange={setSearchTerm}\n disabled={isError}\n />\n <CommandEmpty>\n {searchTerm ? \"No results found.\" : \"Start typing to search\"}\n </CommandEmpty>\n {isError ? (\n <div className=\"p-4 text-sm\">\n {error.message === \"NOT_BUILT_YET\" ? (\n <Callout type=\"info\">\n Search is currently not available in development mode by default.\n <br />\n To still use search in development, run <code>\n zudoku build\n </code>{\" \"}\n and copy the <code>dist/pagefind</code> directory to your{\" \"}\n <code>public</code> directory.\n </Callout>\n ) : (\n \"An error occurred while loading search.\"\n )}\n </div>\n ) : (\n <ResultList\n basePath={options.basePath}\n searchResults={searchResults ?? []}\n searchTerm={searchTerm}\n onClose={onClose}\n maxSubResults={options.maxSubResults}\n />\n )}\n </CommandDialog>\n );\n};\n","import type { ZudokuConfig } from \"../../../config/validators/validate.js\";\nimport { ClientOnly } from \"../../components/ClientOnly.js\";\nimport type { ZudokuPlugin } from \"../../core/plugins.js\";\nimport { PagefindSearch } from \"./PagefindSearch.js\";\n\nexport type PagefindOptions = Extract<\n ZudokuConfig[\"search\"],\n { type: \"pagefind\" }\n> & { basePath?: string };\n\nexport const pagefindSearchPlugin = (\n options: PagefindOptions,\n): ZudokuPlugin => {\n return {\n renderSearch: ({ isOpen, onClose }) => (\n <ClientOnly>\n <PagefindSearch isOpen={isOpen} onClose={onClose} options={options} />\n </ClientOnly>\n ),\n };\n};\n"],"names":["getResults","search","options","maxResults","transformFn","transformedResults","generator","searchResultGenerator","result","processedCount","batch","batchData","transformed","sortSubResults","a","b","aScore","sum","loc","hoverClassname","ResultList","basePath","searchResults","searchTerm","onClose","maxSubResults","navigate","useNavigate","cleanResultUrl","useCallback","url","clean","jsxs","CommandList","jsx","CommandGroup","CommandItem","Link","FileTextIcon","subResult","DEFAULT_RANKING","importPagefind","joinUrl","usePagefind","pagefind","useQuery","_a","_b","_c","_d","PagefindSearch","isOpen","error","isError","setSearchTerm","useState","keepPreviousData","CommandDialog","VisuallyHidden","DialogTitle","CommandInput","CommandEmpty","Callout","pagefindSearchPlugin","ClientOnly"],"mappings":";;;;;;;;;;AAGa,MAAAA,IAAa,OACxBC,GACAC,MACG;AACG,QAAAC,IAAaD,EAAQ,cAAc,IACnCE,IAAcF,EAAQ,qBAAqB,MAAM,KAEjDG,IAA+C,CAAC,GAEhDC,IAAYC,EAAsBN,GAAQG,CAAW;AAE3D,mBAAiBI,KAAUF;AAErB,QADJD,EAAmB,KAAKG,CAAM,GAC1BH,EAAmB,UAAUF,EAAY;AAGxC,SAAAE;AACT;AAEA,gBAAgBE,EACdN,GACAG,GACA;AAEA,MAAIK,IAAiB;AAEd,SAAAA,IAAiBR,EAAO,QAAQ,UAAQ;AACvC,UAAAS,IAAQT,EAAO,QAAQ;AAAA,MAC3BQ;AAAA,MACAA,IAAiB;AAAA,IACnB;AACA,IAAAA,KAAkBC,EAAM;AAElB,UAAAC,IAAY,MAAM,QAAQ,IAAID,EAAM,IAAI,CAACF,MAAWA,EAAO,KAAK,CAAC,CAAC;AAExE,eAAWA,KAAUG,GAAW;AACxB,YAAAC,IAAcR,EAAYI,CAAM;AAEtC,MAAII,MAAgB,OAGTA,MAAgB,MAAQA,KAAe,OAE1C,MAAAJ,IAGA,MAAAI;AAAA,IACR;AAAA,EACF;AAEJ;AC5CA,MAAMC,IAAiB,CAACC,GAAsBC,MAAyB;AAC/D,QAAAC,IAASF,EAAE,mBAAmB;AAAA,IAClC,CAACG,GAAKC,MAAQD,IAAMC,EAAI;AAAA,IACxB;AAAA,EACF;AAKA,SAJeH,EAAE,mBAAmB;AAAA,IAClC,CAACE,GAAKC,MAAQD,IAAMC,EAAI;AAAA,IACxB;AAAA,EACF,IACgBF;AAClB,GAEMG,IAAiB,+EAEVC,IAAa,CAAC;AAAA,EACzB,UAAAC;AAAA,EACA,eAAAC;AAAA,EACA,YAAAC;AAAA,EACA,SAAAC;AAAA,EACA,eAAAC,IAAgB;AAClB,MAMM;AACJ,QAAMC,IAAWC,EAAY,GAEvBC,IAAiBC;AAAA,IACrB,CAACC,MAAgB;AACf,YAAMC,IAAQD,EAAI,QAAQ,SAAS,EAAE;AAC9B,aAAAT,KAAYU,EAAM,WAAWV,CAAQ,IACxCU,EAAM,MAAMV,EAAS,MAAM,IAC3BU;AAAA,IACN;AAAA,IACA,CAACV,CAAQ;AAAA,EACX;AAGE,SAAAW,gBAAAA,EAAA,KAACC,GAAY,EAAA,WAAU,iBACpB,UAAA;AAAA,IAAcV,KAAAD,EAAc,SAAS,KACpCY,gBAAAA,EAAA;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS,GAAGb,EAAc,MAAM,iBAAiBC,CAAU;AAAA,MAAA;AAAA,IAC7D;AAAA,IAEDD,EAAc,IAAI,CAACd,MAClBwB,gBAAAA,EAAA;AAAA,MAACG;AAAA,MAAA;AAAA,QAGC,UAAA;AAAA,UAAAD,gBAAAA,EAAA;AAAA,YAACE;AAAA,YAAA;AAAA,cACC,SAAO;AAAA,cACP,OAAO,GAAG5B,EAAO,KAAK,KAAK,IAAIA,EAAO,GAAG;AAAA,cACzC,WAAWW;AAAA,cACX,UAAU,MAAM;AACd,gBAAKO,EAASE,EAAepB,EAAO,GAAG,CAAC,GAChCgB,EAAA;AAAA,cACV;AAAA,cAEA,iCAACa,GAAK,EAAA,IAAIT,EAAepB,EAAO,GAAG,GACjC,UAAA;AAAA,gBAAA0B,gBAAAA,EAAA,IAACI,GAAa,EAAA,MAAM,IAAI,WAAU,yBAAwB;AAAA,gBACzD9B,EAAO,KAAK;AAAA,cAAA,EACf,CAAA;AAAA,YAAA;AAAA,UACF;AAAA,UACCA,EAAO,YACL,KAAKK,CAAc,EACnB,MAAM,GAAGY,CAAa,EACtB,IAAI,CAACc,MACJL,gBAAAA,EAAA;AAAA,YAACE;AAAA,YAAA;AAAA,cACC,SAAO;AAAA,cAEP,OAAO,GAAG5B,EAAO,KAAK,KAAK,IAAI+B,EAAU,GAAG;AAAA,cAC5C,WAAWpB;AAAA,cACX,UAAU,MAAM;AACd,gBAAKO,EAASE,EAAeW,EAAU,GAAG,CAAC,GACnCf,EAAA;AAAA,cACV;AAAA,cAEA,UAACU,gBAAAA,EAAA,IAAAG,GAAA,EAAK,IAAIT,EAAeW,EAAU,GAAG,GAAG,SAASf,GAChD,UAAAQ,gBAAAA,OAAC,OAAI,EAAA,WAAU,mFACb,UAAA;AAAA,gBAAAE,gBAAAA,EAAA,IAAC,QAAK,EAAA,WAAU,aAAa,UAAAK,EAAU,OAAM;AAAA,gBAC7CL,gBAAAA,EAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAU;AAAA,oBACV,yBAAyB,EAAE,QAAQK,EAAU,QAAQ;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACvD,EAAA,CACF,EACF,CAAA;AAAA,YAAA;AAAA,YAhBK,GAAG/B,EAAO,KAAK,KAAK,IAAI+B,EAAU,GAAG;AAAA,UAkB7C,CAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAxCE,CAAC/B,EAAO,KAAK,SAASA,EAAO,SAASA,EAAO,GAAG,EAAE,KAAK,GAAG;AAAA,IA0ClE,CAAA;AAAA,EAAA,GACH;AAEJ,GCvFMgC,IAAkB;AAAA;AAAA,EAEtB,eAAe;AAAA;AAAA,EAEf,YAAY;AAAA;AAAA,EAEZ,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAClB,GAEMC,IAAiB,CAACpB,MAIlB;AAAA;AAAA,EAA0BqB,EAAQrB,GAAU,uBAAuB;AAAA,GAEnEsB,IAAc,CAACzC,MAA6B;AAChD,QAAM,EAAE,MAAM0C,GAAU,GAAGpC,EAAA,IAAWqC,EAAmB;AAAA,IACvD,UAAU,CAAC,YAAY3C,EAAQ,OAAO;AAAA,IACtC,OAAO;AAAA,IACP,SAAS,YAAY;;AACnB,YAAM0C,IAAW,MAAMH,EAAevC,EAAQ,QAAQ;AACtD,mBAAM0C,EAAS,KAAK,GACpB,MAAMA,EAAS,QAAQ;AAAA,QACrB,SAAS;AAAA,UACP,iBACEE,IAAA5C,EAAQ,YAAR,gBAAA4C,EAAiB,kBAAiBN,EAAgB;AAAA,UACpD,cAAYO,IAAA7C,EAAQ,YAAR,gBAAA6C,EAAiB,eAAcP,EAAgB;AAAA,UAC3D,kBACEQ,IAAA9C,EAAQ,YAAR,gBAAA8C,EAAiB,mBAAkBR,EAAgB;AAAA,UACrD,kBACES,IAAA/C,EAAQ,YAAR,gBAAA+C,EAAiB,mBAAkBT,EAAgB;AAAA,QAAA;AAAA,MACvD,CACD,GAEMI;AAAAA,IACT;AAAA,IACA,SAAS,OAAO,SAAW;AAAA,EAAA,CAC5B;AAED,SAAIpC,EAAO,WAED,QAAA,MAAMA,EAAO,KAAK,GAGrB,EAAE,GAAGA,GAAQ,UAAAoC,EAAS;AAC/B,GAEaM,IAAiB,CAAC;AAAA,EAC7B,QAAAC;AAAA,EACA,SAAA3B;AAAA,EACA,SAAAtB;AACF,MAIM;AACJ,QAAM,EAAE,UAAA0C,GAAU,OAAAQ,GAAO,SAAAC,EAAQ,IAAIV,EAAYzC,CAAO,GAClD,CAACqB,GAAY+B,CAAa,IAAIC,EAAS,EAAE,GAEzC,EAAE,MAAMjC,EAAc,IAAIuB,EAAS;AAAA,IACvC,UAAU,CAAC,mBAAmBtB,CAAU;AAAA,IACxC,SAAS,YAAY;AACnB,YAAMtB,IAAS,OAAM2C,KAAA,gBAAAA,EAAU,OAAOrB;AAClC,aAACtB,IACED,EAAWC,GAAQC,CAAO,IADb,CAAC;AAAA,IAEvB;AAAA,IACA,iBAAiBsD;AAAA,IACjB,SAAS,CAAC,CAACZ,KAAY,CAAC,CAACrB;AAAA,EAAA,CAC1B;AAGC,SAAAS,gBAAAA,EAAA;AAAA,IAACyB;AAAA,IAAA;AAAA,MACC,SAAS,EAAE,cAAc,GAAM;AAAA,MAC/B,SAAS,EAAE,WAAW,gBAAgB;AAAA,MACtC,MAAMN;AAAA,MACN,cAAc3B;AAAA,MAEd,UAAA;AAAA,QAAAU,gBAAAA,MAACwB,GACC,EAAA,UAAAxB,gBAAAA,EAAA,IAACyB,GAAY,EAAA,UAAA,SAAM,CAAA,GACrB;AAAA,QACAzB,gBAAAA,EAAA;AAAA,UAAC0B;AAAA,UAAA;AAAA,YACC,aAAY;AAAA,YACZ,OAAOrC;AAAA,YACP,eAAe+B;AAAA,YACf,UAAUD;AAAA,UAAA;AAAA,QACZ;AAAA,8BACCQ,GAAA,EACE,UAAatC,IAAA,sBAAsB,0BACtC;AAAA,QACC8B,IACEnB,gBAAAA,EAAA,IAAA,OAAA,EAAI,WAAU,eACZ,UAAMkB,EAAA,YAAY,kBAChBpB,gBAAAA,EAAAA,KAAA8B,GAAQ,EAAA,MAAK,QAAO,UAAA;AAAA,UAAA;AAAA,gCAElB,MAAG,EAAA;AAAA,UAAE;AAAA,UACmC5B,gBAAAA,EAAAA,IAAA,UAAK,UAE9C,gBAAA;AAAA,UAAQ;AAAA,UAAI;AAAA,UACEA,gBAAAA,EAAAA,IAAA,UAAK,UAAa,iBAAA;AAAA,UAAO;AAAA,UAAmB;AAAA,UACzDA,gBAAAA,EAAAA,IAAA,UAAK,UAAM,UAAA;AAAA,UAAO;AAAA,QAAA,GACrB,IAEA,0CAEJ,CAAA,IAEAA,gBAAAA,EAAA;AAAA,UAACd;AAAA,UAAA;AAAA,YACC,UAAUlB,EAAQ;AAAA,YAClB,eAAeoB,KAAiB,CAAC;AAAA,YACjC,YAAAC;AAAA,YACA,SAAAC;AAAA,YACA,eAAetB,EAAQ;AAAA,UAAA;AAAA,QAAA;AAAA,MACzB;AAAA,IAAA;AAAA,EAEJ;AAEJ,GC5Ha6D,IAAuB,CAClC7D,OAEO;AAAA,EACL,cAAc,CAAC,EAAE,QAAAiD,GAAQ,SAAA3B,EAAQ,MAC9BU,gBAAAA,EAAAA,IAAA8B,GAAA,EACC,UAAC9B,gBAAAA,EAAA,IAAAgB,GAAA,EAAe,QAAAC,GAAgB,SAAA3B,GAAkB,SAAAtB,EAAkB,CAAA,EACtE,CAAA;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"zudoku.plugin-search-pagefind.js","sources":["../src/lib/plugins/search-pagefind/get-results.tsx","../src/lib/plugins/search-pagefind/ResultList.tsx","../src/lib/plugins/search-pagefind/PagefindSearch.tsx","../src/lib/plugins/search-pagefind/index.tsx"],"sourcesContent":["import type { PagefindOptions } from \"./index.js\";\nimport type { PagefindSearchFragment, PagefindSearchResults } from \"./types.js\";\n\nexport const getResults = async (\n search: PagefindSearchResults,\n options: PagefindOptions,\n) => {\n const maxResults = options.maxResults ?? 10;\n const transformFn = options.transformResults ?? (() => true);\n\n const transformedResults: PagefindSearchFragment[] = [];\n\n const generator = searchResultGenerator(search, transformFn);\n\n for await (const result of generator) {\n transformedResults.push(result);\n if (transformedResults.length >= maxResults) break;\n }\n\n return transformedResults;\n};\n\nasync function* searchResultGenerator(\n search: PagefindSearchResults,\n transformFn: NonNullable<PagefindOptions[\"transformResults\"]>,\n) {\n const batchSize = 5;\n let processedCount = 0;\n\n while (processedCount < search.results.length) {\n const batch = search.results.slice(\n processedCount,\n processedCount + batchSize,\n );\n processedCount += batch.length;\n\n const batchData = await Promise.all(batch.map((result) => result.data()));\n\n for (const result of batchData) {\n const transformed = transformFn(result);\n\n if (transformed === false) {\n // Skip this result\n continue;\n } else if (transformed === true || transformed == null) {\n // Keep the original result\n yield result;\n } else {\n // Return the transformed result\n yield transformed;\n }\n }\n }\n}\n","import { FileTextIcon } from \"lucide-react\";\nimport { useCallback } from \"react\";\nimport { Link, useNavigate } from \"react-router\";\nimport { CommandGroup, CommandItem, CommandList } from \"zudoku/ui/Command.js\";\nimport {\n type PagefindSearchFragment,\n type PagefindSubResult,\n} from \"./types.js\";\n\nconst sortSubResults = (a: PagefindSubResult, b: PagefindSubResult) => {\n const aScore = a.weighted_locations.reduce(\n (sum, loc) => sum + loc.balanced_score,\n 0,\n );\n const bScore = b.weighted_locations.reduce(\n (sum, loc) => sum + loc.balanced_score,\n 0,\n );\n return bScore - aScore;\n};\n\nconst hoverClassname = `cursor-pointer border border-transparent data-[selected=true]:border-border`;\n\nexport const ResultList = ({\n basePath,\n searchResults,\n searchTerm,\n onClose,\n maxSubResults = 4,\n}: {\n basePath?: string;\n searchResults: PagefindSearchFragment[];\n searchTerm: string;\n onClose: () => void;\n maxSubResults?: number;\n}) => {\n const navigate = useNavigate();\n\n const cleanResultUrl = useCallback(\n (url: string) => {\n const clean = url.replace(\".html\", \"\");\n return basePath && clean.startsWith(basePath)\n ? clean.slice(basePath.length)\n : clean;\n },\n [basePath],\n );\n\n return (\n <CommandList className=\"max-h-[450px]\">\n {searchTerm && searchResults.length > 0 && (\n <CommandGroup\n className=\"text-sm text-muted-foreground\"\n heading={`${searchResults.length} results for \"${searchTerm}\"`}\n />\n )}\n {searchResults.map((result) => (\n <CommandGroup\n key={[result.meta.title ?? result.excerpt, result.url].join(\"-\")}\n >\n <CommandItem\n asChild\n value={`${result.meta.title}-${result.url}`}\n className={hoverClassname}\n onSelect={() => {\n void navigate(cleanResultUrl(result.url));\n onClose();\n }}\n >\n <Link to={cleanResultUrl(result.url)}>\n <FileTextIcon size={20} className=\"text-muted-foreground\" />\n {result.meta.title}\n </Link>\n </CommandItem>\n {result.sub_results\n .sort(sortSubResults)\n .slice(0, maxSubResults)\n .map((subResult) => (\n <CommandItem\n asChild\n key={`${result.meta.title}-${subResult.url}`}\n value={`${result.meta.title}-${subResult.url}`}\n className={hoverClassname}\n onSelect={() => {\n void navigate(cleanResultUrl(subResult.url));\n onClose();\n }}\n >\n <Link to={cleanResultUrl(subResult.url)} onClick={onClose}>\n <div className=\"flex flex-col items-start gap-2 ms-2.5 ps-5 border-l border-muted-foreground/50\">\n <span className=\"font-bold\">{subResult.title}</span>\n <span\n className=\"text-[13px] [&_mark]:bg-primary [&_mark]:text-primary-foreground\"\n dangerouslySetInnerHTML={{ __html: subResult.excerpt }}\n />\n </div>\n </Link>\n </CommandItem>\n ))}\n </CommandGroup>\n ))}\n </CommandList>\n );\n};\n","import { VisuallyHidden } from \"@radix-ui/react-visually-hidden\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useState } from \"react\";\nimport { Callout } from \"zudoku/ui/Callout.js\";\nimport {\n CommandDialog,\n CommandEmpty,\n CommandInput,\n} from \"zudoku/ui/Command.js\";\nimport { DialogTitle } from \"zudoku/ui/Dialog.js\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport { getResults } from \"./get-results.js\";\nimport type { PagefindOptions } from \"./index.js\";\nimport { ResultList } from \"./ResultList.js\";\nimport type { Pagefind } from \"./types.js\";\n\nconst DEFAULT_RANKING = {\n // Slightly lower than default because API docs tend to have repetitive terms (parameter names, HTTP methods, etc.)\n termFrequency: 0.8,\n // Lower than default because API documentation pages tend to be longer due to comprehensive endpoint documentation\n pageLength: 0.6,\n // Slightly higher than default because in technical documentation, exact matches should be prioritized\n termSimilarity: 1.2,\n // Slightly lower than default because API docs might have legitimate repetition of terms\n termSaturation: 1.2,\n};\n\nconst importPagefind = (basePath?: string): Promise<Pagefind> =>\n import.meta.env.DEV\n ? // @ts-expect-error TypeScript can't resolve the import\n import(/* @vite-ignore */ \"/pagefind/pagefind.js\")\n : import(/* @vite-ignore */ joinUrl(basePath, \"/pagefind/pagefind.js\"));\n\nconst usePagefind = (options: PagefindOptions) => {\n const { data: pagefind, ...result } = useQuery<Pagefind>({\n queryKey: [\"pagefind\", options.ranking],\n retry: false,\n queryFn: async () => {\n const pagefind = await importPagefind(options.basePath);\n await pagefind.init();\n await pagefind.options({\n ranking: {\n termFrequency:\n options.ranking?.termFrequency ?? DEFAULT_RANKING.termFrequency,\n pageLength: options.ranking?.pageLength ?? DEFAULT_RANKING.pageLength,\n termSimilarity:\n options.ranking?.termSimilarity ?? DEFAULT_RANKING.termSimilarity,\n termSaturation:\n options.ranking?.termSaturation ?? DEFAULT_RANKING.termSaturation,\n },\n });\n\n return pagefind;\n },\n enabled: typeof window !== \"undefined\",\n });\n\n if (result.isError) {\n // eslint-disable-next-line no-console\n console.error(result.error);\n }\n\n return { ...result, pagefind };\n};\n\nexport const PagefindSearch = ({\n isOpen,\n onClose,\n options,\n}: {\n isOpen: boolean;\n onClose: () => void;\n options: PagefindOptions;\n}) => {\n const { pagefind, error, isError } = usePagefind(options);\n const [searchTerm, setSearchTerm] = useState(\"\");\n\n const { data: searchResults } = useQuery({\n queryKey: [\"pagefind-search\", searchTerm],\n queryFn: async () => {\n const search = await pagefind?.search(searchTerm);\n if (!search) return [];\n return getResults(search, options);\n },\n placeholderData: keepPreviousData,\n enabled: !!pagefind && !!searchTerm,\n });\n\n return (\n <CommandDialog\n command={{ shouldFilter: false }}\n content={{ className: \"max-w-[750px]\" }}\n open={isOpen}\n onOpenChange={onClose}\n >\n <VisuallyHidden>\n <DialogTitle>Search</DialogTitle>\n </VisuallyHidden>\n <CommandInput\n placeholder=\"Search...\"\n value={searchTerm}\n onValueChange={setSearchTerm}\n disabled={isError}\n />\n <CommandEmpty>\n {searchTerm ? \"No results found.\" : \"Start typing to search\"}\n </CommandEmpty>\n {isError ? (\n <div className=\"p-4 text-sm\">\n {error.message === \"NOT_BUILT_YET\" ? (\n <Callout type=\"info\">\n Search is currently not available in development mode by default.\n <br />\n To still use search in development, run <code>\n zudoku build\n </code>{\" \"}\n and copy the <code>dist/pagefind</code> directory to your{\" \"}\n <code>public</code> directory.\n </Callout>\n ) : (\n \"An error occurred while loading search.\"\n )}\n </div>\n ) : (\n <ResultList\n basePath={options.basePath}\n searchResults={searchResults ?? []}\n searchTerm={searchTerm}\n onClose={onClose}\n maxSubResults={options.maxSubResults}\n />\n )}\n </CommandDialog>\n );\n};\n","import type { ZudokuConfig } from \"../../../config/validators/validate.js\";\nimport { ClientOnly } from \"../../components/ClientOnly.js\";\nimport type { ZudokuPlugin } from \"../../core/plugins.js\";\nimport { PagefindSearch } from \"./PagefindSearch.js\";\n\nexport type PagefindOptions = Extract<\n ZudokuConfig[\"search\"],\n { type: \"pagefind\" }\n> & { basePath?: string };\n\nexport const pagefindSearchPlugin = (\n options: PagefindOptions,\n): ZudokuPlugin => {\n return {\n renderSearch: ({ isOpen, onClose }) => (\n <ClientOnly>\n <PagefindSearch isOpen={isOpen} onClose={onClose} options={options} />\n </ClientOnly>\n ),\n };\n};\n"],"names":["getResults","search","options","maxResults","transformFn","transformedResults","generator","searchResultGenerator","result","processedCount","batch","batchData","transformed","sortSubResults","a","b","aScore","sum","loc","hoverClassname","ResultList","basePath","searchResults","searchTerm","onClose","maxSubResults","navigate","useNavigate","cleanResultUrl","useCallback","url","clean","jsxs","CommandList","jsx","CommandGroup","CommandItem","Link","FileTextIcon","subResult","DEFAULT_RANKING","importPagefind","joinUrl","usePagefind","pagefind","useQuery","_a","_b","_c","_d","PagefindSearch","isOpen","error","isError","setSearchTerm","useState","keepPreviousData","CommandDialog","VisuallyHidden","DialogTitle","CommandInput","CommandEmpty","Callout","pagefindSearchPlugin","ClientOnly"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zudoku.plugins.js","sources":["../src/lib/core/plugins.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport { type ReactElement } from \"react\";\nimport { type RouteObject } from \"react-router\";\nimport type { Sidebar } from \"../../config/validators/SidebarSchema.js\";\nimport { MdxComponentsType } from \"../util/MdxComponents.js\";\nimport {\n
|
|
1
|
+
{"version":3,"file":"zudoku.plugins.js","sources":["../src/lib/core/plugins.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport { type ReactElement } from \"react\";\nimport { type RouteObject } from \"react-router\";\nimport type { Sidebar } from \"../../config/validators/SidebarSchema.js\";\nimport { type MdxComponentsType } from \"../util/MdxComponents.js\";\nimport {\n type ApiIdentity,\n type ZudokuContext,\n type ZudokuEvents,\n} from \"./ZudokuContext.js\";\n\nexport type ZudokuPlugin =\n | CommonPlugin\n | ProfileMenuPlugin\n | NavigationPlugin\n | ApiIdentityPlugin\n | SearchProviderPlugin\n | EventConsumerPlugin;\n\nexport type { RouteObject };\n\nexport interface NavigationPlugin {\n getRoutes: () => RouteObject[];\n getSidebar?: (path: string, context: ZudokuContext) => Promise<Sidebar>;\n}\n\nexport const createApiIdentityPlugin = (\n plugin: ApiIdentityPlugin,\n): ApiIdentityPlugin => plugin;\n\nexport const createProfileMenuPlugin = (\n plugin: ProfileMenuPlugin,\n): ProfileMenuPlugin => plugin;\n\nexport interface ApiIdentityPlugin {\n getIdentities: (context: ZudokuContext) => Promise<ApiIdentity[]>;\n}\n\nexport interface SearchProviderPlugin {\n renderSearch: (o: {\n isOpen: boolean;\n onClose: () => void;\n }) => React.JSX.Element | null;\n}\n\nexport interface ProfileMenuPlugin {\n getProfileMenuItems: (context: ZudokuContext) => ProfileNavigationItem[];\n}\n\nexport type ProfileNavigationItem = {\n label: string;\n path?: string;\n weight?: number;\n category?: \"top\" | \"middle\" | \"bottom\";\n children?: ProfileNavigationItem[];\n icon?: LucideIcon;\n};\n\nexport interface CommonPlugin {\n initialize?: (\n context: ZudokuContext,\n ) => Promise<void | boolean> | void | boolean;\n getHead?: () => ReactElement | undefined;\n getMdxComponents?: () => MdxComponentsType;\n}\n\nexport type EventConsumerPlugin<Event extends ZudokuEvents = ZudokuEvents> = {\n events: { [K in keyof Event]: Event[K] };\n};\n\nexport const isEventConsumerPlugin = (\n obj: ZudokuPlugin,\n): obj is EventConsumerPlugin =>\n \"events\" in obj && typeof obj.events === \"object\";\n\nexport const isProfileMenuPlugin = (\n obj: ZudokuPlugin,\n): obj is ProfileMenuPlugin =>\n \"getProfileMenuItems\" in obj && typeof obj.getProfileMenuItems === \"function\";\n\nexport const isNavigationPlugin = (\n obj: ZudokuPlugin,\n): obj is NavigationPlugin =>\n \"getRoutes\" in obj && typeof obj.getRoutes === \"function\";\n\nexport const isSearchPlugin = (\n obj: ZudokuPlugin,\n): obj is SearchProviderPlugin =>\n \"renderSearch\" in obj && typeof obj.renderSearch === \"function\";\n\nexport const needsInitialization = (obj: ZudokuPlugin): obj is CommonPlugin =>\n \"initialize\" in obj && typeof obj.initialize === \"function\";\n\nexport const hasHead = (obj: ZudokuPlugin): obj is CommonPlugin =>\n \"getHead\" in obj && typeof obj.getHead === \"function\";\n\nexport const isMdxProviderPlugin = (obj: ZudokuPlugin): obj is CommonPlugin =>\n \"getMdxComponents\" in obj && typeof obj.getMdxComponents === \"function\";\n\nexport const isApiIdentityPlugin = (\n obj: ZudokuPlugin,\n): obj is ApiIdentityPlugin =>\n \"getIdentities\" in obj && typeof obj.getIdentities === \"function\";\n"],"names":["createApiIdentityPlugin","plugin","createProfileMenuPlugin","isEventConsumerPlugin","obj","isProfileMenuPlugin","isNavigationPlugin","isSearchPlugin","needsInitialization","hasHead","isMdxProviderPlugin","isApiIdentityPlugin"],"mappings":"AA0Ba,MAAAA,IAA0B,CACrCC,MACsBA,GAEXC,IAA0B,CACrCD,MACsBA,GAsCXE,IAAwB,CACnCC,MAEA,YAAYA,KAAO,OAAOA,EAAI,UAAW,UAE9BC,IAAsB,CACjCD,MAEA,yBAAyBA,KAAO,OAAOA,EAAI,uBAAwB,YAExDE,IAAqB,CAChCF,MAEA,eAAeA,KAAO,OAAOA,EAAI,aAAc,YAEpCG,IAAiB,CAC5BH,MAEA,kBAAkBA,KAAO,OAAOA,EAAI,gBAAiB,YAE1CI,IAAsB,CAACJ,MAClC,gBAAgBA,KAAO,OAAOA,EAAI,cAAe,YAEtCK,IAAU,CAACL,MACtB,aAAaA,KAAO,OAAOA,EAAI,WAAY,YAEhCM,IAAsB,CAACN,MAClC,sBAAsBA,KAAO,OAAOA,EAAI,oBAAqB,YAElDO,IAAsB,CACjCP,MAEA,mBAAmBA,KAAO,OAAOA,EAAI,iBAAkB;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zudoku",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"homepage": "https://zudoku.dev",
|
|
6
6
|
"repository": {
|
|
@@ -178,6 +178,7 @@
|
|
|
178
178
|
"esm-loader-css": "^1.0.3",
|
|
179
179
|
"estree-util-value-to-estree": "3.3.2",
|
|
180
180
|
"express": "4.21.2",
|
|
181
|
+
"fast-equals": "5.2.2",
|
|
181
182
|
"glob": "11.0.1",
|
|
182
183
|
"graphql": "16.10.0",
|
|
183
184
|
"graphql-type-json": "0.3.2",
|
|
@@ -190,6 +191,7 @@
|
|
|
190
191
|
"loglevel": "1.9.2",
|
|
191
192
|
"lru-cache": "11.0.2",
|
|
192
193
|
"lucide-react": "0.475.0",
|
|
194
|
+
"minimatch": "10.0.1",
|
|
193
195
|
"nanoevents": "^9.1.0",
|
|
194
196
|
"next-themes": "0.4.4",
|
|
195
197
|
"oauth4webapi": "2.17.0",
|
package/src/app/entry.server.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import "virtual:zudoku-theme.css";
|
|
14
14
|
import "vite/modulepreload-polyfill";
|
|
15
15
|
import { BootstrapStatic, ServerError } from "zudoku/components";
|
|
16
|
+
import { NO_DEHYDRATE } from "../lib/components/cache.js";
|
|
16
17
|
import type { FileWritingResponse } from "../vite/prerender/FileWritingResponse.js";
|
|
17
18
|
import "./main.css";
|
|
18
19
|
import { getRoutesByConfig } from "./main.js";
|
|
@@ -115,10 +116,15 @@ export const render = async ({
|
|
|
115
116
|
);
|
|
116
117
|
|
|
117
118
|
transformStream.on("finish", () => {
|
|
119
|
+
const dehydrated = dehydrate(queryClient, {
|
|
120
|
+
shouldDehydrateQuery: (query) =>
|
|
121
|
+
!query.queryKey.includes(NO_DEHYDRATE),
|
|
122
|
+
});
|
|
123
|
+
|
|
118
124
|
response.end(
|
|
119
125
|
htmlEnd?.replace(
|
|
120
126
|
"</body>",
|
|
121
|
-
`<script>window.DATA
|
|
127
|
+
`<script>window.DATA=${JSON.stringify(dehydrated)}</script></body>`,
|
|
122
128
|
),
|
|
123
129
|
);
|
|
124
130
|
});
|
|
@@ -6,12 +6,14 @@ export const InlineCode = ({
|
|
|
6
6
|
className,
|
|
7
7
|
children,
|
|
8
8
|
selectOnClick,
|
|
9
|
+
onClick,
|
|
9
10
|
}: {
|
|
10
11
|
className?: string;
|
|
11
12
|
children: ReactNode;
|
|
12
13
|
selectOnClick?: boolean;
|
|
14
|
+
onClick?: () => void;
|
|
13
15
|
}) => (
|
|
14
|
-
<SelectOnClick asChild enabled={selectOnClick}>
|
|
16
|
+
<SelectOnClick asChild enabled={selectOnClick} onClick={onClick}>
|
|
15
17
|
<code
|
|
16
18
|
className={cn(
|
|
17
19
|
"font-mono border p-1 py-0.5 rounded bg-border/50 dark:bg-border/70 [overflow-wrap:anywhere]",
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Helmet } from "@zudoku/react-helmet-async";
|
|
2
|
-
import { Suspense, useEffect,
|
|
3
|
-
import { Outlet,
|
|
2
|
+
import { Suspense, useEffect, type ReactNode } from "react";
|
|
3
|
+
import { Outlet, useNavigation } from "react-router";
|
|
4
4
|
import { useSpinDelay } from "spin-delay";
|
|
5
5
|
import { useScrollToAnchor } from "../util/useScrollToAnchor.js";
|
|
6
6
|
import { useScrollToTop } from "../util/useScrollToTop.js";
|
|
7
|
-
import { useViewportAnchor } from "./context/ViewportAnchorContext.js";
|
|
8
7
|
import { useZudoku } from "./context/ZudokuContext.js";
|
|
9
8
|
import { Header } from "./Header.js";
|
|
10
9
|
import { Main } from "./Main.js";
|
|
@@ -18,29 +17,17 @@ const LoadingFallback = () => (
|
|
|
18
17
|
);
|
|
19
18
|
|
|
20
19
|
export const Layout = ({ children }: { children?: ReactNode }) => {
|
|
21
|
-
const location = useLocation();
|
|
22
|
-
const { setActiveAnchor } = useViewportAnchor();
|
|
23
20
|
const { meta, authentication } = useZudoku();
|
|
24
21
|
|
|
25
22
|
useScrollToAnchor();
|
|
26
23
|
useScrollToTop();
|
|
27
24
|
|
|
28
|
-
const previousLocationPath = useRef(location.pathname);
|
|
29
|
-
|
|
30
25
|
useEffect(() => {
|
|
31
26
|
// Initialize the authentication plugin
|
|
32
27
|
authentication?.onPageLoad?.();
|
|
33
28
|
}, [authentication]);
|
|
34
29
|
|
|
35
|
-
|
|
36
|
-
// always reset on location change
|
|
37
|
-
if (location.pathname !== previousLocationPath.current) {
|
|
38
|
-
setActiveAnchor("");
|
|
39
|
-
}
|
|
40
|
-
previousLocationPath.current = location.pathname;
|
|
41
|
-
}, [location.pathname, setActiveAnchor]);
|
|
42
|
-
|
|
43
|
-
// Page transition is happening: https://reactrouter.com/start/framework/pending-ui#global-pending-navigation
|
|
30
|
+
// Page transition is happening: https://reactrouter.com/start/framework/pending-navigation
|
|
44
31
|
const isNavigating = Boolean(useNavigation().location);
|
|
45
32
|
const showSpinner = useSpinDelay(isNavigating, {
|
|
46
33
|
delay: 300,
|
|
@@ -44,7 +44,7 @@ export const MobileTopNavigation = () => {
|
|
|
44
44
|
</li>
|
|
45
45
|
{topNavigation.filter(isHiddenItem(isAuthenticated)).map((item) => (
|
|
46
46
|
<li key={item.label}>
|
|
47
|
-
<button onClick={() => setDrawerOpen(false)}>
|
|
47
|
+
<button type="button" onClick={() => setDrawerOpen(false)}>
|
|
48
48
|
<TopNavItem {...item} />
|
|
49
49
|
</button>
|
|
50
50
|
</li>
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { cx } from "class-variance-authority";
|
|
2
2
|
import { Suspense } from "react";
|
|
3
3
|
import { NavLink, useNavigation } from "react-router";
|
|
4
|
-
import { TopNavigationItem } from "../../config/validators/common.js";
|
|
4
|
+
import type { TopNavigationItem } from "../../config/validators/common.js";
|
|
5
5
|
import { useAuth } from "../authentication/hook.js";
|
|
6
|
-
import {
|
|
7
|
-
import { joinPath } from "../util/joinPath.js";
|
|
6
|
+
import { joinUrl } from "../util/joinUrl.js";
|
|
8
7
|
import { useCurrentNavigation, useZudoku } from "./context/ZudokuContext.js";
|
|
9
8
|
import { traverseSidebar } from "./navigation/utils.js";
|
|
10
9
|
import { Slotlet } from "./SlotletProvider.js";
|
|
11
10
|
|
|
12
11
|
export const isHiddenItem =
|
|
13
12
|
(isAuthenticated?: boolean) =>
|
|
14
|
-
(item: { display?: "auth" | "anon" | "always" }) => {
|
|
13
|
+
(item: { display?: "auth" | "anon" | "always" | "hide" }): boolean => {
|
|
14
|
+
if (item.display === "hide") return false;
|
|
15
15
|
return (
|
|
16
16
|
(item.display === "auth" && isAuthenticated) ||
|
|
17
17
|
(item.display === "anon" && !isAuthenticated) ||
|
|
@@ -24,17 +24,18 @@ export const TopNavigation = () => {
|
|
|
24
24
|
const { topNavigation } = useZudoku();
|
|
25
25
|
const { isAuthenticated } = useAuth();
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const filteredItems = topNavigation.filter(isHiddenItem(isAuthenticated));
|
|
28
|
+
|
|
29
|
+
if (filteredItems.length === 0) {
|
|
29
30
|
return <style>{`:root { --top-nav-height: 0px; }`}</style>;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
return (
|
|
33
34
|
<Suspense>
|
|
34
|
-
<div className="
|
|
35
|
+
<div className="items-center justify-between px-8 h-[--top-nav-height] hidden lg:flex text-sm">
|
|
35
36
|
<nav className="text-sm">
|
|
36
37
|
<ul className="flex flex-row items-center gap-8">
|
|
37
|
-
{
|
|
38
|
+
{filteredItems.map((item) => (
|
|
38
39
|
<li key={item.id}>
|
|
39
40
|
<TopNavItem {...item} />
|
|
40
41
|
</li>
|
|
@@ -66,15 +67,10 @@ export const TopNavItem = ({
|
|
|
66
67
|
defaultLink ??
|
|
67
68
|
(currentSidebar
|
|
68
69
|
? traverseSidebar(currentSidebar, (item) => {
|
|
69
|
-
if (item.type === "doc") return
|
|
70
|
+
if (item.type === "doc") return joinUrl(item.id);
|
|
70
71
|
})
|
|
71
|
-
:
|
|
72
|
-
|
|
73
|
-
if (!first) {
|
|
74
|
-
throw new ZudokuError("Page not found.", {
|
|
75
|
-
developerHint: `No links found in top navigation for '${id}'. Check that the sidebar isn't empty or that a default link is set.`,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
72
|
+
: joinUrl(id)) ??
|
|
73
|
+
joinUrl(id);
|
|
78
74
|
|
|
79
75
|
return (
|
|
80
76
|
// We don't use isActive here because it has to be inside the sidebar,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MDXProvider } from "@mdx-js/react";
|
|
2
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
2
3
|
import { Helmet } from "@zudoku/react-helmet-async";
|
|
3
4
|
import { ThemeProvider } from "next-themes";
|
|
4
5
|
import {
|
|
@@ -59,6 +60,7 @@ const ZudokoInner = memo(
|
|
|
59
60
|
[stagger, didNavigate],
|
|
60
61
|
);
|
|
61
62
|
const navigation = useNavigation();
|
|
63
|
+
const queryClient = useQueryClient();
|
|
62
64
|
|
|
63
65
|
useEffect(() => {
|
|
64
66
|
if (didNavigate) {
|
|
@@ -67,7 +69,9 @@ const ZudokoInner = memo(
|
|
|
67
69
|
setDidNavigate(true);
|
|
68
70
|
}, [didNavigate, navigation.location]);
|
|
69
71
|
|
|
70
|
-
const [zudokuContext] = useState(
|
|
72
|
+
const [zudokuContext] = useState(
|
|
73
|
+
() => new ZudokuContext(props, queryClient),
|
|
74
|
+
);
|
|
71
75
|
|
|
72
76
|
const heads = props.plugins
|
|
73
77
|
?.flatMap((plugin) => (hasHead(plugin) ? (plugin.getHead?.() ?? []) : []))
|
|
@@ -13,3 +13,11 @@ export const useCache = () => {
|
|
|
13
13
|
},
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* If a query has this key in its queryKey, it will not put its result in the dehydrated state in the SSR.
|
|
19
|
+
*
|
|
20
|
+
* This is useful if the query should only be suspended and not included in the initial HTML response.
|
|
21
|
+
* (e.g. too large in size, or not needed for the initial page load)
|
|
22
|
+
*/
|
|
23
|
+
export const NO_DEHYDRATE = "no-dehydrate";
|
|
@@ -94,14 +94,11 @@ export const ViewportAnchorProvider = ({ children }: PropsWithChildren) => {
|
|
|
94
94
|
window.innerHeight + window.scrollY >= document.body.scrollHeight;
|
|
95
95
|
|
|
96
96
|
if (hasReachedTop) {
|
|
97
|
-
// reset the active anchor when we reach the top
|
|
98
97
|
setActiveAnchor("");
|
|
99
98
|
} else if (hasReachedBottom) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
setActiveAnchor(lastItem?.id ?? "");
|
|
104
|
-
});
|
|
99
|
+
const lastItem = Array.from(elements).pop();
|
|
100
|
+
const lastId = lastItem?.id ?? "";
|
|
101
|
+
setActiveAnchor(lastId);
|
|
105
102
|
}
|
|
106
103
|
};
|
|
107
104
|
|
|
@@ -2,9 +2,9 @@ import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
|
|
|
2
2
|
import { createContext, useContext } from "react";
|
|
3
3
|
import { matchPath, useLocation } from "react-router";
|
|
4
4
|
import { useAuth } from "../../authentication/hook.js";
|
|
5
|
-
import { ZudokuContext } from "../../core/ZudokuContext.js";
|
|
6
|
-
import {
|
|
7
|
-
import { CACHE_KEYS } from "../cache.js";
|
|
5
|
+
import type { ZudokuContext } from "../../core/ZudokuContext.js";
|
|
6
|
+
import { joinUrl } from "../../util/joinUrl.js";
|
|
7
|
+
import { CACHE_KEYS, NO_DEHYDRATE } from "../cache.js";
|
|
8
8
|
import { traverseSidebar } from "../navigation/utils.js";
|
|
9
9
|
|
|
10
10
|
export const ZudokuReactContext = createContext<ZudokuContext | undefined>(
|
|
@@ -26,7 +26,7 @@ export const useApiIdentities = () => {
|
|
|
26
26
|
|
|
27
27
|
return useQuery({
|
|
28
28
|
queryFn: getApiIdentities,
|
|
29
|
-
queryKey:
|
|
29
|
+
queryKey: CACHE_KEYS.API_IDENTITIES,
|
|
30
30
|
});
|
|
31
31
|
};
|
|
32
32
|
|
|
@@ -39,13 +39,13 @@ export const useCurrentNavigation = () => {
|
|
|
39
39
|
matchPath(route, location.pathname),
|
|
40
40
|
);
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
let currentSidebarItem = Object.entries(sidebars).find(([, sidebar]) => {
|
|
43
43
|
return traverseSidebar(sidebar, (item) => {
|
|
44
44
|
const itemId =
|
|
45
45
|
item.type === "doc"
|
|
46
|
-
?
|
|
46
|
+
? joinUrl(item.id)
|
|
47
47
|
: item.type === "category" && item.link
|
|
48
|
-
?
|
|
48
|
+
? joinUrl(item.link.id)
|
|
49
49
|
: undefined;
|
|
50
50
|
|
|
51
51
|
if (itemId === location.pathname) {
|
|
@@ -57,9 +57,18 @@ export const useCurrentNavigation = () => {
|
|
|
57
57
|
topNavigation.find((t) => t.id === currentSidebarItem?.[0]) ??
|
|
58
58
|
topNavigation.find((item) => matchPath(item.id, location.pathname));
|
|
59
59
|
|
|
60
|
+
if (
|
|
61
|
+
currentTopNavItem &&
|
|
62
|
+
!currentSidebarItem &&
|
|
63
|
+
currentTopNavItem.id in sidebars
|
|
64
|
+
) {
|
|
65
|
+
currentSidebarItem = ["", sidebars[currentTopNavItem.id]!];
|
|
66
|
+
}
|
|
67
|
+
|
|
60
68
|
const { data } = useSuspenseQuery({
|
|
61
69
|
queryFn: () => getPluginSidebar(location.pathname),
|
|
62
|
-
|
|
70
|
+
// We just want to suspend here and don't store in SSR dehydrated state
|
|
71
|
+
queryKey: ["plugin-sidebar", NO_DEHYDRATE, location.pathname],
|
|
63
72
|
});
|
|
64
73
|
|
|
65
74
|
const hideSidebar =
|