zudoku 0.1.1-dev.11 → 0.1.1-dev.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/app/DevPortal.js +2 -15
  2. package/dist/app/DevPortal.js.map +1 -1
  3. package/dist/app/Router.d.ts +4 -0
  4. package/dist/app/Router.js +20 -0
  5. package/dist/app/Router.js.map +1 -0
  6. package/dist/vite/config.d.ts +2 -2
  7. package/dist/vite/config.js +13 -8
  8. package/dist/vite/config.js.map +1 -1
  9. package/dist/vite/plugin-api.js +1 -1
  10. package/dist/vite/plugin-api.js.map +1 -1
  11. package/dist/vite/plugin-auth.js +1 -1
  12. package/dist/vite/plugin-docs.js +1 -1
  13. package/dist/vite/plugin-docs.js.map +1 -1
  14. package/package.json +2 -2
  15. package/src/app/App.tsx +0 -30
  16. package/src/app/DevPortal.tsx +0 -115
  17. package/src/app/Heading.tsx +0 -60
  18. package/src/app/authentication/authentication.ts +0 -18
  19. package/src/app/authentication/clerk.ts +0 -47
  20. package/src/app/authentication/openid.ts +0 -192
  21. package/src/app/components/AnchorLink.tsx +0 -19
  22. package/src/app/components/CategoryHeading.tsx +0 -16
  23. package/src/app/components/Dialog.tsx +0 -119
  24. package/src/app/components/DynamicIcon.tsx +0 -60
  25. package/src/app/components/Header.tsx +0 -69
  26. package/src/app/components/Input.tsx +0 -24
  27. package/src/app/components/Layout.tsx +0 -56
  28. package/src/app/components/Markdown.tsx +0 -37
  29. package/src/app/components/SyntaxHighlight.tsx +0 -94
  30. package/src/app/components/TopNavigation.tsx +0 -32
  31. package/src/app/components/context/ComponentsContext.tsx +0 -24
  32. package/src/app/components/context/DevPortalProvider.ts +0 -54
  33. package/src/app/components/context/PluginSystem.ts +0 -0
  34. package/src/app/components/context/ThemeContext.tsx +0 -46
  35. package/src/app/components/context/ViewportAnchorContext.tsx +0 -139
  36. package/src/app/components/navigation/SideNavigation.tsx +0 -18
  37. package/src/app/components/navigation/SideNavigationCategory.tsx +0 -74
  38. package/src/app/components/navigation/SideNavigationItem.tsx +0 -143
  39. package/src/app/components/navigation/SideNavigationWrapper.tsx +0 -15
  40. package/src/app/components/navigation/useNavigationCollapsibleState.ts +0 -27
  41. package/src/app/components/navigation/util.ts +0 -38
  42. package/src/app/core/DevPortalContext.ts +0 -164
  43. package/src/app/core/helmet.ts +0 -5
  44. package/src/app/core/icons.tsx +0 -1
  45. package/src/app/core/plugins.ts +0 -43
  46. package/src/app/core/router.tsx +0 -1
  47. package/src/app/core/types/combine.ts +0 -16
  48. package/src/app/main.css +0 -137
  49. package/src/app/main.tsx +0 -9
  50. package/src/app/oas/graphql/index.ts +0 -422
  51. package/src/app/oas/graphql/server.ts +0 -10
  52. package/src/app/oas/parser/dereference/index.ts +0 -59
  53. package/src/app/oas/parser/dereference/resolveRef.ts +0 -32
  54. package/src/app/oas/parser/index.ts +0 -94
  55. package/src/app/oas/parser/schemas/v3.0.json +0 -1489
  56. package/src/app/oas/parser/schemas/v3.1.json +0 -1298
  57. package/src/app/oas/parser/upgrade/index.ts +0 -108
  58. package/src/app/plugins/api-key/SettingsApiKeys.tsx +0 -22
  59. package/src/app/plugins/api-key/index.tsx +0 -123
  60. package/src/app/plugins/markdown/MdxPage.tsx +0 -128
  61. package/src/app/plugins/markdown/Toc.tsx +0 -122
  62. package/src/app/plugins/markdown/generateRoutes.tsx +0 -72
  63. package/src/app/plugins/markdown/index.tsx +0 -31
  64. package/src/app/plugins/openapi/ColorizedParam.tsx +0 -82
  65. package/src/app/plugins/openapi/MakeRequest.tsx +0 -49
  66. package/src/app/plugins/openapi/MethodBadge.tsx +0 -36
  67. package/src/app/plugins/openapi/OperationList.tsx +0 -117
  68. package/src/app/plugins/openapi/OperationListItem.tsx +0 -55
  69. package/src/app/plugins/openapi/ParameterList.tsx +0 -32
  70. package/src/app/plugins/openapi/ParameterListItem.tsx +0 -60
  71. package/src/app/plugins/openapi/RequestBodySidecarBox.tsx +0 -51
  72. package/src/app/plugins/openapi/ResponsesSidecarBox.tsx +0 -60
  73. package/src/app/plugins/openapi/Select.tsx +0 -35
  74. package/src/app/plugins/openapi/Sidecar.tsx +0 -160
  75. package/src/app/plugins/openapi/SidecarBox.tsx +0 -36
  76. package/src/app/plugins/openapi/graphql/fragment-masking.ts +0 -111
  77. package/src/app/plugins/openapi/graphql/gql.ts +0 -70
  78. package/src/app/plugins/openapi/graphql/graphql.ts +0 -795
  79. package/src/app/plugins/openapi/graphql/index.ts +0 -2
  80. package/src/app/plugins/openapi/index.tsx +0 -142
  81. package/src/app/plugins/openapi/playground/Playground.tsx +0 -309
  82. package/src/app/plugins/openapi/queries.graphql +0 -6
  83. package/src/app/plugins/openapi/util/generateSchemaExample.ts +0 -59
  84. package/src/app/plugins/openapi/util/urql.ts +0 -8
  85. package/src/app/plugins/openapi/worker/createSharedWorkerClient.ts +0 -60
  86. package/src/app/plugins/openapi/worker/worker.ts +0 -30
  87. package/src/app/plugins/redirect/index.tsx +0 -20
  88. package/src/app/tailwind.ts +0 -72
  89. package/src/app/ui/Button.tsx +0 -56
  90. package/src/app/ui/Callout.tsx +0 -87
  91. package/src/app/ui/Card.tsx +0 -82
  92. package/src/app/ui/Note.tsx +0 -58
  93. package/src/app/ui/Tabs.tsx +0 -52
  94. package/src/app/util/MdxComponents.tsx +0 -70
  95. package/src/app/util/cn.ts +0 -6
  96. package/src/app/util/createVariantComponent.tsx +0 -30
  97. package/src/app/util/createWaitForNotify.ts +0 -18
  98. package/src/app/util/groupBy.ts +0 -24
  99. package/src/app/util/joinPath.tsx +0 -10
  100. package/src/app/util/pastellize.ts +0 -25
  101. package/src/app/util/slugify.ts +0 -3
  102. package/src/app/util/traverseNavigation.ts +0 -55
  103. package/src/app/util/useScrollToAnchor.ts +0 -38
  104. package/src/app/util/useScrollToTop.ts +0 -13
@@ -1,32 +0,0 @@
1
- import { cx } from "class-variance-authority";
2
- import { NavLink } from "react-router-dom";
3
-
4
- import { useDevPortal } from "./context/DevPortalProvider.js";
5
-
6
- export const TopNavigation = () => {
7
- const { navigation } = useDevPortal();
8
-
9
- return (
10
- <nav className="border-b border-border text-sm px-12 h-[--top-nav-height]">
11
- <ul className="flex flex-row items-center gap-8">
12
- {navigation.map((item) => (
13
- <li key={item.label}>
14
- <NavLink
15
- className={({ isActive }) =>
16
- cx(
17
- "block py-3.5 font-medium -mb-px border-b-2",
18
- isActive
19
- ? "border-primary text-foreground"
20
- : "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
21
- )
22
- }
23
- to={item.path}
24
- >
25
- {item.label}
26
- </NavLink>
27
- </li>
28
- ))}
29
- </ul>
30
- </nav>
31
- );
32
- };
@@ -1,24 +0,0 @@
1
- import {
2
- createContext,
3
- useContext,
4
- type ComponentProps,
5
- type ComponentType,
6
- } from "react";
7
- import { Header } from "../Header.js";
8
-
9
- export const DEFAULT_COMPONENTS = {
10
- Header,
11
- };
12
-
13
- export type ComponentsContextType = {
14
- Header?: ComponentType<ComponentProps<typeof Header>>;
15
- };
16
-
17
- const ComponentsContext =
18
- createContext<Required<ComponentsContextType>>(DEFAULT_COMPONENTS);
19
-
20
- export const ComponentsProvider = ComponentsContext.Provider;
21
-
22
- export const useComponents = () => {
23
- return useContext(ComponentsContext);
24
- };
@@ -1,54 +0,0 @@
1
- import { useSuspenseQuery } from "@tanstack/react-query";
2
- import { createContext, useContext } from "react";
3
- import { matchPath, useLocation } from "react-router-dom";
4
- import { DevPortalContext } from "../../core/DevPortalContext.js";
5
-
6
- const DevPortalReactContext = createContext<DevPortalContext | undefined>(
7
- undefined,
8
- );
9
-
10
- export const DevPortalProvider = DevPortalReactContext.Provider;
11
-
12
- export const useDevPortal = () => {
13
- const context = useContext(DevPortalReactContext);
14
-
15
- if (!context) {
16
- throw new Error("useDevPortal must be used within a DevPortalProvider.");
17
- }
18
-
19
- return context;
20
- };
21
-
22
- export const useApiIdentities = () => {
23
- const { getApiIdentities } = useDevPortal();
24
- return useSuspenseQuery({
25
- queryFn: getApiIdentities,
26
- queryKey: ["api-keys"],
27
- });
28
- };
29
-
30
- export const useTopNavigationItem = () => {
31
- const { navigation } = useDevPortal();
32
- const location = useLocation();
33
-
34
- return navigation.find((item) =>
35
- matchPath({ path: item.path, end: false }, location.pathname),
36
- );
37
- };
38
-
39
- export const useNavigation = () => {
40
- const { getNavigation } = useDevPortal();
41
- const navItem = useTopNavigationItem();
42
-
43
- const path = navItem?.path ?? "";
44
-
45
- return useSuspenseQuery({
46
- queryFn: async () => {
47
- return {
48
- items: [...(navItem?.categories ?? []), ...(await getNavigation(path))],
49
- currentTopNavItem: navItem,
50
- };
51
- },
52
- queryKey: ["navigation", path],
53
- });
54
- };
File without changes
@@ -1,46 +0,0 @@
1
- import {
2
- createContext,
3
- type ReactNode,
4
- useCallback,
5
- useEffect,
6
- useState,
7
- useContext,
8
- } from "react";
9
-
10
- const ThemeContext = createContext<readonly [boolean, () => void]>([
11
- false,
12
- () => {},
13
- ]);
14
-
15
- export const useTheme = () => {
16
- const context = useContext(ThemeContext);
17
- if (!context) {
18
- throw new Error("useTheme must be used within a ThemeProvider");
19
- }
20
- return context;
21
- };
22
-
23
- export const ThemeProvider = (props: { children: ReactNode }) => {
24
- const [dark, setDark] = useState(false);
25
-
26
- // On mount, read the preferred theme from the persistence
27
- useEffect(() => {
28
- const theme = localStorage.getItem("theme");
29
- const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
30
- const isDark = theme === "dark" || (!theme && prefersDark.matches);
31
-
32
- setDark(isDark);
33
- }, [dark]);
34
-
35
- // To toggle between dark and light modes
36
- const toggle = useCallback(() => {
37
- const toggled = !dark;
38
- document.documentElement.classList.toggle("dark", toggled);
39
- localStorage.setItem("theme", toggled ? "dark" : "light");
40
- setDark(toggled);
41
- }, [dark]);
42
-
43
- const value = [dark, toggle] as const;
44
-
45
- return <ThemeContext.Provider value={value} {...props} />;
46
- };
@@ -1,139 +0,0 @@
1
- import {
2
- type ReactNode,
3
- createContext,
4
- useCallback,
5
- useContext,
6
- useEffect,
7
- useMemo,
8
- useRef,
9
- useState,
10
- } from "react";
11
-
12
- type AnchorContextType = {
13
- activeAnchor?: string;
14
- setActiveAnchor: (anchor: string) => void;
15
- observe: (element: HTMLElement | null) => void;
16
- unobserve: (element: HTMLElement | null) => void;
17
- };
18
-
19
- const ViewportAnchorContext = createContext<AnchorContextType | undefined>(
20
- undefined,
21
- );
22
-
23
- export const useViewportAnchor = () => {
24
- const context = useContext(ViewportAnchorContext);
25
-
26
- if (!context) {
27
- throw new Error(
28
- "useViewportAnchor must be used within a CurrentAnchorProvider",
29
- );
30
- }
31
-
32
- return context;
33
- };
34
-
35
- export const useRegisterAnchorElement = () => {
36
- const elementRef = useRef<HTMLElement | null>(null);
37
-
38
- const { observe, unobserve } = useViewportAnchor();
39
-
40
- useEffect(() => {
41
- const element = elementRef.current;
42
-
43
- if (!element) return;
44
-
45
- observe(element);
46
-
47
- return () => unobserve(element);
48
- }, [observe, unobserve]);
49
-
50
- const setRef = useCallback((el: HTMLElement | null) => {
51
- if (!el) return;
52
- elementRef.current = el;
53
- }, []);
54
-
55
- return { ref: setRef };
56
- };
57
-
58
- export const ViewportAnchorProvider = ({
59
- children,
60
- }: {
61
- children: ReactNode;
62
- }) => {
63
- const [activeAnchor, setActiveAnchor] = useState("");
64
- const observerRef = useRef<IntersectionObserver | null>(null);
65
- const registeredElements = useRef(new Set<HTMLElement>());
66
-
67
- useEffect(() => {
68
- observerRef.current = new IntersectionObserver(
69
- (entries) => {
70
- for (const entry of entries) {
71
- if (entry.isIntersecting && entry.target.id) {
72
- setActiveAnchor(entry.target.id);
73
- }
74
- }
75
- },
76
- {
77
- // 115px is the height of the sticky header
78
- // see --header-height in `main.css`
79
- rootMargin: "115px 0px -80% 0px",
80
- threshold: 0.75,
81
- },
82
- );
83
-
84
- return () => observerRef.current?.disconnect();
85
- }, []);
86
-
87
- useEffect(() => {
88
- const elements = registeredElements.current;
89
- const handleScroll = () => {
90
- const hasReachedTop = window.scrollY === 0;
91
- const hasReachedBottom =
92
- window.innerHeight + window.scrollY >= document.body.scrollHeight;
93
-
94
- if (hasReachedTop) {
95
- // reset the active anchor when we reach the top
96
- setActiveAnchor("");
97
- } else if (hasReachedBottom) {
98
- requestIdleCallback(() => {
99
- // set the last anchor when we reach the bottom
100
- const lastItem = Array.from(elements).pop();
101
- setActiveAnchor(lastItem?.id ?? "");
102
- });
103
- }
104
- };
105
-
106
- document.addEventListener("scroll", handleScroll);
107
-
108
- return () => {
109
- elements.clear();
110
- document.removeEventListener("scroll", handleScroll);
111
- };
112
- }, []);
113
-
114
- const observeFns = useMemo(() => {
115
- return {
116
- observe: (element: HTMLElement | null) => {
117
- if (!element || !observerRef.current) return;
118
- registeredElements.current.add(element);
119
- observerRef.current.observe(element);
120
- },
121
- unobserve: (element: HTMLElement | null) => {
122
- if (!element || !observerRef.current) return;
123
- registeredElements.current.delete(element);
124
- observerRef.current.unobserve(element);
125
- },
126
- };
127
- }, []);
128
-
129
- const value = useMemo(
130
- () => ({ activeAnchor, setActiveAnchor, ...observeFns }),
131
- [activeAnchor, setActiveAnchor, observeFns],
132
- );
133
-
134
- return (
135
- <ViewportAnchorContext.Provider value={value}>
136
- {children}
137
- </ViewportAnchorContext.Provider>
138
- );
139
- };
@@ -1,18 +0,0 @@
1
- import { useRef } from "react";
2
-
3
- import { useNavigation } from "../context/DevPortalProvider.js";
4
- import { SideNavigationCategory } from "./SideNavigationCategory.js";
5
- import { SideNavigationWrapper } from "./SideNavigationWrapper.js";
6
-
7
- export const SideNavigation = () => {
8
- const navRef = useRef<HTMLDivElement | null>(null);
9
- const navigation = useNavigation();
10
-
11
- return (
12
- <SideNavigationWrapper ref={navRef}>
13
- {navigation.data.items.map((category) => (
14
- <SideNavigationCategory key={category.label} category={category} />
15
- ))}
16
- </SideNavigationWrapper>
17
- );
18
- };
@@ -1,74 +0,0 @@
1
- import * as Collapsible from "@radix-ui/react-collapsible";
2
- import { ChevronRightIcon } from "lucide-react";
3
- import { useLocation } from "react-router-dom";
4
- import type { NavigationCategory } from "../../core/DevPortalContext.js";
5
- import { cn } from "../../util/cn.js";
6
- import { joinPath } from "../../util/joinPath.js";
7
- import { useTopNavigationItem } from "../context/DevPortalProvider.js";
8
- import { useViewportAnchor } from "../context/ViewportAnchorContext.js";
9
- import { SideNavigationItem } from "./SideNavigationItem.js";
10
- import { useNavigationCollapsibleState } from "./useNavigationCollapsibleState.js";
11
- import { checkHasActiveItem, isPathItem } from "./util.js";
12
-
13
- export const SideNavigationCategory = ({
14
- category,
15
- }: {
16
- category: NavigationCategory;
17
- }) => {
18
- const { activeAnchor } = useViewportAnchor();
19
- const navItem = useTopNavigationItem();
20
- const location = useLocation();
21
-
22
- const isCollapsible = category.collapsible ?? true;
23
-
24
- const [isOpen, setIsOpen] = useNavigationCollapsibleState({
25
- item: category,
26
- path: navItem?.path ?? "",
27
- defaultOpen: () =>
28
- !isCollapsible ||
29
- category.expanded ||
30
- checkHasActiveItem(category, location.pathname, navItem?.path ?? ""),
31
- });
32
-
33
- return (
34
- <Collapsible.Root
35
- key={category.label}
36
- open={isOpen}
37
- onOpenChange={() => setIsOpen((prev) => !prev)}
38
- >
39
- {category.label.length > 0 && (
40
- <Collapsible.Trigger asChild={isCollapsible} disabled={!isCollapsible}>
41
- <h5
42
- className={cn(
43
- "flex group items-center justify-between cursor-pointer font-semibold text-foreground/90 px-[--padding-nav-item] py-1.5 rounded-lg transition-colors duration-300 -mx-[--padding-nav-item]",
44
- isCollapsible ? "hover:bg-accent" : "cursor-auto",
45
- )}
46
- >
47
- {category.label}
48
- {isCollapsible && (
49
- <ChevronRightIcon
50
- className="group-data-[state=open]:rotate-90 transition"
51
- size={16}
52
- />
53
- )}
54
- </h5>
55
- </Collapsible.Trigger>
56
- )}
57
- <Collapsible.Content className="CollapsibleContent -mx-[--padding-nav-item]">
58
- {/* margin on Collapsible.Content will lead jumpiness when animating because it's not added to the calculated height */}
59
- <ul className="space-y-0.5 mt-1.5 mb-4 ms-3">
60
- {category.children.map((item) => (
61
- <SideNavigationItem
62
- key={isPathItem(item) ? item.path + item.label : item.href}
63
- category={category}
64
- item={item}
65
- activeAnchor={activeAnchor}
66
- currentTopNavItem={navItem}
67
- basePath={joinPath(navItem?.path, category.path)}
68
- />
69
- ))}
70
- </ul>
71
- </Collapsible.Content>
72
- </Collapsible.Root>
73
- );
74
- };
@@ -1,143 +0,0 @@
1
- import * as Collapsible from "@radix-ui/react-collapsible";
2
- import { cva } from "class-variance-authority";
3
- import { ChevronRightIcon, ExternalLinkIcon } from "lucide-react";
4
- import { NavLink, useLocation } from "react-router-dom";
5
-
6
- import type {
7
- NavigationCategory,
8
- NavigationCategoryItem,
9
- NavigationItem,
10
- } from "../../core/DevPortalContext.js";
11
- import { cn } from "../../util/cn.js";
12
- import { joinPath } from "../../util/joinPath.js";
13
- import { AnchorLink } from "../AnchorLink.js";
14
- import { DynamicIcon, isValidIcon } from "../DynamicIcon.js";
15
- import { useNavigationCollapsibleState } from "./useNavigationCollapsibleState.js";
16
- import { checkHasActiveItem, isLinkItem, isPathItem } from "./util.js";
17
-
18
- export const linkItem = cva(
19
- "flex px-[--padding-nav-item] py-1.5 rounded-lg hover:bg-accent transition-colors duration-300",
20
- {
21
- variants: {
22
- isActive: {
23
- true: "text-primary font-medium",
24
- false: "text-foreground/80",
25
- },
26
- },
27
- },
28
- );
29
-
30
- export const DATA_ANCHOR_ATTR = "data-anchor";
31
-
32
- export const SideNavigationItem = ({
33
- category,
34
- item,
35
- activeAnchor,
36
- currentTopNavItem,
37
- basePath = "",
38
- }: {
39
- category: NavigationCategory;
40
- item: NavigationCategoryItem;
41
- activeAnchor?: string;
42
- currentTopNavItem?: NavigationItem;
43
- basePath?: string;
44
- }) => {
45
- const currentPath = isPathItem(item) ? joinPath(basePath, item.path) : "";
46
- const location = useLocation();
47
-
48
- const [isOpen, setIsOpen] = useNavigationCollapsibleState({
49
- item,
50
- path: currentPath,
51
- defaultOpen: () => checkHasActiveItem(item, location.pathname, currentPath),
52
- });
53
-
54
- if (isLinkItem(item)) {
55
- const classes = cn(
56
- "flex items-center gap-2",
57
- linkItem({ isActive: item.href === location.pathname }),
58
- );
59
- return item.href.startsWith("http") ? (
60
- <a
61
- className={classes}
62
- href={item.href}
63
- target="_blank"
64
- rel="noopener noreferrer"
65
- >
66
- {item.label}
67
- <ExternalLinkIcon size={14} />
68
- </a>
69
- ) : (
70
- <NavLink className={classes} to={item.href}>
71
- {item.label}
72
- </NavLink>
73
- );
74
- }
75
-
76
- const linkContent = (
77
- <div className="flex justify-between w-full">
78
- <div className="flex items-center gap-2 truncate w-full">
79
- {isValidIcon(item.icon) && <DynamicIcon name={item.icon} size={16} />}
80
- {typeof item.label !== "string" ? (
81
- item.label
82
- ) : (
83
- <span className="truncate">{item.label}</span>
84
- )}
85
- </div>
86
- {item.children && (
87
- <ChevronRightIcon
88
- size={16}
89
- className="transition shrink-0 group-data-[state=open]:rotate-90"
90
- />
91
- )}
92
- </div>
93
- );
94
-
95
- return (
96
- <li title={typeof item.label === "string" ? item.label : item.title}>
97
- {item.children ? (
98
- <Collapsible.Root
99
- open={isOpen}
100
- onOpenChange={() => setIsOpen((prev) => !prev)}
101
- className="flex flex-col"
102
- >
103
- <Collapsible.Trigger
104
- className={cn("group text-start", linkItem({ isActive: false }))}
105
- >
106
- {linkContent}
107
- </Collapsible.Trigger>
108
- <Collapsible.Content className="CollapsibleContent ms-[calc(var(--padding-nav-item)*1.125)]">
109
- <ul className="mt-1 border-border border-l ps-1.5">
110
- {item.children.map((child) => (
111
- <SideNavigationItem
112
- key={isPathItem(child) ? child.path : child.href}
113
- category={category}
114
- item={child}
115
- activeAnchor={activeAnchor}
116
- currentTopNavItem={currentTopNavItem}
117
- basePath={currentPath}
118
- />
119
- ))}
120
- </ul>
121
- </Collapsible.Content>
122
- </Collapsible.Root>
123
- ) : item.path.startsWith("#") ? (
124
- <AnchorLink
125
- to={item.path}
126
- {...{ [DATA_ANCHOR_ATTR]: item.path }}
127
- className={linkItem({
128
- isActive: item.path.slice(1) === activeAnchor,
129
- })}
130
- >
131
- {linkContent}
132
- </AnchorLink>
133
- ) : (
134
- <NavLink
135
- className={({ isActive }) => linkItem({ isActive })}
136
- to={currentPath}
137
- >
138
- {linkContent}
139
- </NavLink>
140
- )}
141
- </li>
142
- );
143
- };
@@ -1,15 +0,0 @@
1
- import { forwardRef, type PropsWithChildren } from "react";
2
-
3
- export const SideNavigationWrapper = forwardRef<
4
- HTMLDivElement,
5
- PropsWithChildren
6
- >(({ children }, ref) => {
7
- return (
8
- <nav
9
- className="hidden lg:flex flex-col fixed text-sm overflow-y-auto shrink-0 p-[--padding-nav-item] -mx-[--padding-nav-item] pb-20 pt-[--padding-content-top] w-[--side-nav-width] h-[calc(100%-var(--header-height))] scroll-pt-2 gap-2"
10
- ref={ref}
11
- >
12
- {children}
13
- </nav>
14
- );
15
- });
@@ -1,27 +0,0 @@
1
- import { useEffect, useRef, useState } from "react";
2
- import { useLocation } from "react-router-dom";
3
- import type { NavigationNode } from "../../util/traverseNavigation.js";
4
- import { checkHasActiveItem } from "./util.js";
5
-
6
- export const useNavigationCollapsibleState = ({
7
- item,
8
- defaultOpen,
9
- path,
10
- }: {
11
- item: NavigationNode;
12
- defaultOpen: () => boolean;
13
- path: string;
14
- }) => {
15
- const [isOpen, setIsOpen] = useState(defaultOpen);
16
- const location = useLocation();
17
- const previousLocationPath = useRef(location.pathname);
18
-
19
- useEffect(() => {
20
- if (!isOpen && previousLocationPath.current !== location.pathname) {
21
- setIsOpen(checkHasActiveItem(item, location.pathname, path));
22
- }
23
- previousLocationPath.current = location.pathname;
24
- }, [isOpen, item, path, location.pathname]);
25
-
26
- return [isOpen, setIsOpen] as const;
27
- };
@@ -1,38 +0,0 @@
1
- import { matchPath } from "react-router-dom";
2
- import type {
3
- HrefNavigationCategoryItem,
4
- PathNavigationCategoryItem,
5
- } from "../../core/DevPortalContext.js";
6
- import {
7
- traverseNavigationNode,
8
- type NavigationNode,
9
- } from "../../util/traverseNavigation.js";
10
-
11
- export const isPathItem = (
12
- item: NavigationNode,
13
- ): item is PathNavigationCategoryItem => "path" in item;
14
-
15
- export const isLinkItem = (
16
- item: NavigationNode,
17
- ): item is HrefNavigationCategoryItem => "href" in item;
18
-
19
- /**
20
- * Recursively checks if the current item or any of its children are active.
21
- */
22
- export const checkHasActiveItem = (
23
- item: NavigationNode,
24
- locationPath: string,
25
- basePath: string,
26
- ) => {
27
- return Boolean(
28
- traverseNavigationNode(
29
- item,
30
- (node, fullPath) => {
31
- if (isPathItem(node) && matchPath(fullPath, locationPath)) {
32
- return true;
33
- }
34
- },
35
- basePath,
36
- ),
37
- );
38
- };