Skip to content

Commit

Permalink
Performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
iway1 committed Apr 23, 2023
1 parent 8e99d0c commit 9c68bcd
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 74 deletions.
8 changes: 4 additions & 4 deletions packages/trpc-panel/src/react-app/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export function RootComponent({
}) {
return (
<HeadersContextProvider>
<SiteNavigationContextProvider>
<AllPathsContextProvider rootRouter={rootRouter}>
<AllPathsContextProvider rootRouter={rootRouter}>
<SiteNavigationContextProvider>
<ClientProviders trpc={trpc} options={options}>
<HotKeysContextProvider>
<SearchOverlay>
Expand All @@ -41,8 +41,8 @@ export function RootComponent({
</SearchOverlay>
</HotKeysContextProvider>
</ClientProviders>
</AllPathsContextProvider>
</SiteNavigationContextProvider>
</SiteNavigationContextProvider>
</AllPathsContextProvider>
</HeadersContextProvider>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import React, { MutableRefObject, ReactNode, useEffect, useRef } from "react";
import { Chevron } from "@src/react-app/components/Chevron";
import { useSiteNavigationContext } from "@src/react-app/components/contexts/SiteNavigationContext";
import {
collapsables,
useCollapsableIsShowing,
useSiteNavigationContext,
} from "@src/react-app/components/contexts/SiteNavigationContext";
import {
backgroundColor,
solidColorBg,
solidColorBorder,
} from "@src/react-app/components/style-utils";

export type ColorSchemeType = "query" | "mutation" | "router" | "neutral" | "subscription";

export type ColorSchemeType =
| "query"
| "mutation"
| "router"
| "neutral"
| "subscription";
export function CollapsableSection({
titleElement,
fullPath,
Expand All @@ -24,8 +32,9 @@ export function CollapsableSection({
isRoot?: boolean;
focusOnScrollRef?: MutableRefObject<HTMLFormElement | null>;
}) {
const { has, togglePath, scrollToPathIfMatches } = useSiteNavigationContext();
const shown = has(fullPath);
const { scrollToPathIfMatches } = useSiteNavigationContext();
const shown = useCollapsableIsShowing(fullPath);

const containerRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (shown && containerRef.current) {
Expand Down Expand Up @@ -59,7 +68,7 @@ export function CollapsableSection({
>
{collapsable ? (
<button
onClick={() => togglePath(fullPath)}
onClick={() => collapsables.toggle(fullPath)}
className="flex flex-row justify-between items-center p-1 "
>
<span className="flex flex-row">
Expand Down
32 changes: 22 additions & 10 deletions packages/trpc-panel/src/react-app/components/SideNav.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from "react";
import React, { useCallback } from "react";
import type { ParsedRouter } from "../../parse/parseRouter";
import type { ParsedProcedure } from "@src/parse/parseProcedure";
import { useSiteNavigationContext } from "@src/react-app/components/contexts/SiteNavigationContext";
import {
collapsables,
useCollapsableIsShowing,
useSiteNavigationContext,
} from "@src/react-app/components/contexts/SiteNavigationContext";
import { Chevron } from "@src/react-app/components/Chevron";
import { colorSchemeForNode } from "@src/react-app/components/style-utils";
import { ItemTypeIcon } from "@src/react-app/components/ItemTypeIcon";
Expand Down Expand Up @@ -31,13 +35,13 @@ function SideNavItem({
node: ParsedRouter | ParsedProcedure;
path: string[];
}) {
const { togglePath, has, markForScrollTo } = useSiteNavigationContext();
const shown = has(path) || path.length == 0;
const { markForScrollTo } = useSiteNavigationContext();
const shown = useCollapsableIsShowing(path) || path.length === 0;

function onClick() {
togglePath(path);
const onClick = useCallback(function onClick() {
collapsables.toggle(path);
markForScrollTo(path);
}
}, []);

return (
<>
Expand Down Expand Up @@ -66,9 +70,17 @@ function SideNavItem({
{shown && node.nodeType === "router" && (
<div className="pl-2 flex flex-col items-start space-y-2 self-stretch">
{Object.entries(node.children).map(([key, node]) => {
const newPath = path.concat([key]);
const k = newPath.join(",");
return <SideNavItem path={newPath} node={node} key={k} />;
return (
<SideNavItem
path={
node.nodeType === "procedure"
? node.pathFromRootRouter
: node.path
}
node={node}
key={key}
/>
);
})}
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { useAllPaths } from "@src/react-app/components/contexts/AllPathsContext";
import React, {
createContext,
ReactNode,
useContext,
useMemo,
useRef,
useState,
} from "react";
import { create } from "zustand";

const Context = createContext<{
has: (path: string[]) => boolean;
hidePath: (path: string[]) => void;
showPath: (path: string[]) => void;
togglePath: (path: string[]) => void;
scrollToPathIfMatches: (path: string[], element: Element) => boolean;
markForScrollTo: (path: string[]) => void;
openAndNavigateTo: (path: string[], closeOthers?: boolean) => void;
Expand All @@ -25,40 +23,90 @@ function forAllPaths(path: string[], callback: (current: string) => void) {
}
}

export function SiteNavigationContextProvider({
children,
}: {
children: ReactNode;
}) {
const [shownPaths, setShownPaths] = useState<Set<string>>(new Set());
const collapsablesStore = {
current: null as null | ReturnType<typeof create>,
};

const scrollToPathRef = useRef<string[] | null>(null);
function initialCollapsableStoreValues(allPaths: string[]) {
const vals: Record<string, boolean> = {};

for (const path of allPaths) {
vals[path] = false;
}
return vals;
}

function initCollapsablesStore(allPaths: string[]) {
collapsablesStore.current = create<any>(() => ({
...initialCollapsableStoreValues(allPaths),
}));
}

function useInitCollapsablesStore(allPaths: string[]) {
const hasInitted = useRef(false);

if (!hasInitted.current) {
initCollapsablesStore(allPaths);
hasInitted.current = true;
}
}

function hidePath(path: string[]) {
const newPaths = new Set<string>(shownPaths);
export const collapsables = (() => {
const hide = (path: string[]) => {
const pathJoined = path.join(".");
forAllPaths(path, (current) => {
if (pathJoined.length <= current.length) newPaths.delete(current);
if (pathJoined.length <= current.length) {
collapsablesStore.current?.setState({
[current]: false,
});
}
});
setShownPaths(newPaths);
}

function showPath(path: string[]) {
const newPaths = new Set<string>(shownPaths);
};
const show = (path: string[]) => {
forAllPaths(path, (current) => {
newPaths.add(current);
collapsablesStore.current?.setState({
[current]: true,
});
});
setShownPaths(newPaths);
}
};
return {
hide,
show,
toggle(path: string[]) {
const state = collapsablesStore.current!.getState() as any;
if (state[path.join(".")]) {
hide(path);
} else {
show(path);
}
},
hideAll() {
const state = collapsablesStore.current! as any;
const newValue: Record<string, boolean> = {};
for (const path in state) {
newValue[path] = false;
}
collapsablesStore.current!.setState(newValue);
},
};
})();

function has(path: string[]) {
return shownPaths.has(path.join("."));
}
export function useCollapsableIsShowing(path: string[]) {
const p = useMemo(() => {
return path.join(".");
}, []);
return collapsablesStore.current!((s) => (s as any)[p]);
}

function toggle(path: string[]) {
if (has(path)) hidePath(path);
else showPath(path);
}
export function SiteNavigationContextProvider({
children,
}: {
children: ReactNode;
}) {
const allPaths = useAllPaths();
useInitCollapsablesStore(allPaths.pathsArray);

const scrollToPathRef = useRef<string[] | null>(null);

function scrollToPathIfMatches(path: string[], element: Element) {
if (
Expand All @@ -81,21 +129,16 @@ export function SiteNavigationContextProvider({
}

function openAndNavigateTo(path: string[], hideOthers?: boolean) {
const newSet = hideOthers ? new Set<string>() : new Set(shownPaths);
forAllPaths(path, (p) => {
newSet.add(p);
});
if (hideOthers) {
collapsables.hideAll();
}
collapsables.show(path);
markForScrollTo(path);
setShownPaths(newSet);
}

return (
<Context.Provider
value={{
hidePath,
showPath,
has,
togglePath: toggle,
scrollToPathIfMatches,
markForScrollTo,
openAndNavigateTo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,23 @@ export function DocumentationSection({
{hasParams && (
<DocumentationSubsection title="Params">
<table>
{Object.entries(extraData.parameterDescriptions).map(
([key, value]) => (
<tr
key={key}
className="border-b border-separatorLine flex-row space-x-2"
>
<td className="text-sm text-neutralText font-bold align-top py-2">
{`${key}: `}
</td>
<td className="pl-4 text-sm text-gray-500 py-2">
{`${value}`}
</td>
</tr>
)
)}
<tbody>
{Object.entries(extraData.parameterDescriptions).map(
([key, value]) => (
<tr
key={key}
className="border-b border-separatorLine flex-row space-x-2"
>
<td className="text-sm text-neutralText font-bold align-top py-2">
{`${key}: `}
</td>
<td className="pl-4 text-sm text-gray-500 py-2">
{`${value}`}
</td>
</tr>
)
)}
</tbody>
</table>
</DocumentationSubsection>
)}
Expand Down

0 comments on commit 9c68bcd

Please sign in to comment.