Skip to content

Commit f5c21d6

Browse files
committed
V2.2.0 - Embedded mode
1 parent 8693fa5 commit f5c21d6

File tree

11 files changed

+185
-27
lines changed

11 files changed

+185
-27
lines changed

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "remix-development-tools",
33
"description": "Remix development tools.",
44
"author": "Alem Tuzlak",
5-
"version": "2.1.4",
5+
"version": "2.2.0",
66
"license": "MIT",
77
"keywords": [
88
"remix",
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import clsx from "clsx";
2+
import { InjectedStyles, RemixDevToolsProps } from "./RemixDevTools";
3+
import { useSettingsContext } from "./context/useRDTContext";
4+
import { useOutletAugment } from "./hooks/useOutletAugment";
5+
import { useSetRouteBoundaries } from "./hooks/useSetRouteBoundaries";
6+
import { useTimelineHandler } from "./hooks/useTimelineHandler";
7+
import { ContentPanel } from "./layout/ContentPanel";
8+
import { MainPanel } from "./layout/MainPanel";
9+
import { Tabs } from "./layout/Tabs";
10+
import { REMIX_DEV_TOOLS } from "./utils/storage";
11+
import { useLocation } from "@remix-run/react";
12+
import { RDTContextProvider } from "./context/RDTContext";
13+
import { useState, useEffect } from "react";
14+
15+
export interface EmbeddedDevToolsProps extends RemixDevToolsProps {
16+
mainPanelClassName?: string;
17+
className?: string;
18+
}
19+
const Embedded = ({ plugins, mainPanelClassName, className }: EmbeddedDevToolsProps) => {
20+
useTimelineHandler();
21+
useOutletAugment();
22+
useSetRouteBoundaries();
23+
const { settings } = useSettingsContext();
24+
const { position } = settings;
25+
const leftSideOriented = position.includes("left");
26+
return (
27+
<div id={REMIX_DEV_TOOLS} className={clsx("remix-dev-tools", className)}>
28+
<MainPanel className={mainPanelClassName} isEmbedded isOpen={true}>
29+
<Tabs plugins={plugins} />
30+
<ContentPanel leftSideOriented={leftSideOriented} plugins={plugins} />
31+
</MainPanel>
32+
</div>
33+
);
34+
};
35+
36+
let hydrating = true;
37+
38+
function useHydrated() {
39+
const [hydrated, setHydrated] = useState(() => !hydrating);
40+
41+
useEffect(function hydrate() {
42+
hydrating = false;
43+
setHydrated(true);
44+
}, []);
45+
46+
return hydrated;
47+
}
48+
49+
const EmbeddedDevTools = ({ requireUrlFlag, plugins, mainPanelClassName, className }: EmbeddedDevToolsProps) => {
50+
const hydrated = useHydrated();
51+
const url = useLocation().search;
52+
53+
if (!hydrated) return null;
54+
if (requireUrlFlag && !url.includes("rdt=true")) return null;
55+
56+
return (
57+
<RDTContextProvider>
58+
<InjectedStyles />
59+
<Embedded mainPanelClassName={mainPanelClassName} className={className} plugins={plugins} />
60+
</RDTContextProvider>
61+
);
62+
};
63+
64+
export { EmbeddedDevTools };

src/RemixDevTools/RemixDevTools.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import {
2121
} from "./utils/storage";
2222
import { useSyncStateWhenDetached } from "./hooks/detached/useSyncStateWhenDetached";
2323

24-
const InjectedStyles = () => <style dangerouslySetInnerHTML={{ __html: rdtStylesheet }} />;
24+
export const InjectedStyles = () => <style dangerouslySetInnerHTML={{ __html: rdtStylesheet }} />;
2525

26-
const RemixDevTools = ({ plugins }: RemixDevToolsProps) => {
26+
const DevTools = ({ plugins }: RemixDevToolsProps) => {
2727
useTimelineHandler();
2828
useOutletAugment();
2929
useResetDetachmentCheck();
@@ -85,7 +85,7 @@ export interface RemixDevToolsProps {
8585
plugins?: Tab[];
8686
}
8787

88-
const RDTWithContext = ({ requireUrlFlag, plugins }: RemixDevToolsProps) => {
88+
const RemixDevTools = ({ requireUrlFlag, plugins }: RemixDevToolsProps) => {
8989
const hydrated = useHydrated();
9090
const url = useLocation().search;
9191

@@ -95,9 +95,9 @@ const RDTWithContext = ({ requireUrlFlag, plugins }: RemixDevToolsProps) => {
9595
return (
9696
<RDTContextProvider>
9797
<InjectedStyles />
98-
<RemixDevTools plugins={plugins} />
98+
<DevTools plugins={plugins} />
9999
</RDTContextProvider>
100100
);
101101
};
102102

103-
export { RDTWithContext as RemixDevTools };
103+
export { RemixDevTools };

src/RemixDevTools/index.ts

-3
This file was deleted.

src/RemixDevTools/layout/MainPanel.tsx

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import clsx from "clsx";
22
import { useResize } from "../hooks/useResize";
3-
import {
4-
useDetachedWindowControls,
5-
useSettingsContext,
6-
} from "../context/useRDTContext";
3+
import { useDetachedWindowControls, useSettingsContext } from "../context/useRDTContext";
74
import { useState } from "react";
85
import { useAttachWindowListener } from "../hooks/useAttachListener";
96
import { useDebounce } from "../hooks/useDebounce";
107

118
interface MainPanelProps {
129
children: React.ReactNode;
1310
isOpen: boolean;
11+
isEmbedded?: boolean;
12+
className?: string;
1413
}
1514

1615
const useResizeDetachedPanel = () => {
@@ -22,7 +21,7 @@ const useResizeDetachedPanel = () => {
2221
useAttachWindowListener("resize", debounce, isDetached);
2322
};
2423

25-
const MainPanel = ({ children, isOpen }: MainPanelProps) => {
24+
const MainPanel = ({ children, isOpen, isEmbedded = false, className }: MainPanelProps) => {
2625
const { settings } = useSettingsContext();
2726
const { detachedWindow } = useDetachedWindowControls();
2827
const { height } = settings;
@@ -33,12 +32,14 @@ const MainPanel = ({ children, isOpen }: MainPanelProps) => {
3332
<div
3433
style={{
3534
zIndex: 9998,
36-
height: detachedWindow ? window.innerHeight : height,
35+
...(!isEmbedded && { height: detachedWindow ? window.innerHeight : height }),
3736
}}
3837
className={clsx(
39-
"rdt-duration-600 rdt-fixed rdt-bottom-0 rdt-left-0 rdt-box-border rdt-flex rdt-w-screen rdt-flex-col rdt-overflow-auto rdt-bg-[#212121] rdt-text-white rdt-opacity-0 rdt-transition-all",
38+
"rdt-duration-600 rdt-box-border rdt-flex rdt-w-screen rdt-flex-col rdt-overflow-auto rdt-bg-[#212121] rdt-text-white rdt-opacity-0 rdt-transition-all",
4039
isOpen ? "rdt-opacity-100 rdt-drop-shadow-2xl" : "rdt-h-0",
41-
isResizing && "rdt-cursor-grabbing "
40+
isResizing && "rdt-cursor-grabbing ",
41+
!isEmbedded && "rdt-fixed rdt-bottom-0 rdt-left-0",
42+
className
4243
)}
4344
>
4445
<div

src/RemixDevTools/layout/Tabs.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ declare global {
2020
}
2121

2222
interface TabsProps {
23-
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
23+
setIsOpen?: React.Dispatch<React.SetStateAction<boolean>>;
2424
plugins?: Tab[];
2525
}
2626

@@ -104,7 +104,7 @@ const Tabs = ({ plugins, setIsOpen }: TabsProps) => {
104104
onClick={() => setSettings({ shouldConnectWithForge: true })}
105105
/>
106106
)}
107-
{!detachedWindow && (
107+
{!detachedWindow && setIsOpen && (
108108
<>
109109
{!detachedWindowOwner && (
110110
<CopySlash

src/index.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
import { useRemixForgeSocket, initClient, initServer, RemixDevTools } from "./RemixDevTools";
2-
import { type Tab } from "./RemixDevTools/tabs";
3-
1+
import { RemixDevTools } from "./RemixDevTools/RemixDevTools";
2+
import { type Tab } from "./RemixDevTools/tabs/index";
3+
// Names exports
4+
export { useRemixForgeSocket } from "./RemixDevTools/hooks/useRemixForgeSocket";
5+
export { initClient, initServer } from "./RemixDevTools/init/project";
6+
export { EmbeddedDevTools } from "./RemixDevTools/EmbeddedDevTools";
7+
// Type exports
8+
export type { EmbeddedDevToolsProps } from "./RemixDevTools/EmbeddedDevTools";
9+
export type { RemixDevToolsProps } from "./RemixDevTools/RemixDevTools";
410
export type Plugin = (...args: any) => Tab;
511

6-
export { useRemixForgeSocket, initClient, initServer };
12+
// Default export
713
export default RemixDevTools;

src/remix-app-for-testing/app/routes/_index.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { ActionArgs } from "@remix-run/node";
22
import { json, redirect, type LoaderArgs, defer } from "@remix-run/node";
33
import type { V2_MetaFunction } from "@remix-run/node";
4-
import { Link, useFetcher, useLoaderData, useSubmit } from "@remix-run/react";
4+
import { Link, useFetcher, useSubmit } from "@remix-run/react";
55

66
export const meta: V2_MetaFunction = () => {
77
return [
@@ -54,6 +54,7 @@ export default function Index() {
5454
<button onClick={() => submit(null, { method: "PUT", action: "/" })}>
5555
SUBMIT Action PUT
5656
</button>
57+
5758
<Link to="/login">Login</Link>
5859
<ul>
5960
<li>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import type { ActionArgs } from "@remix-run/node";
2+
import { redirect, type LoaderArgs, defer } from "@remix-run/node";
3+
import type { V2_MetaFunction } from "@remix-run/node";
4+
import { Link, useFetcher, useSubmit } from "@remix-run/react";
5+
import { EmbeddedDevTools } from "remix-development-tools";
6+
7+
export const meta: V2_MetaFunction = () => {
8+
return [
9+
{ title: "New Remix App" },
10+
{ name: "description", content: "Welcome to Remix!" },
11+
];
12+
};
13+
14+
export const loader = async ({ request }: LoaderArgs) => {
15+
const test = new Promise((resolve) => {
16+
setTimeout(() => {
17+
resolve("test");
18+
}, 1000);
19+
})
20+
return defer({ message: "Hello World!", test });
21+
};
22+
23+
export const action = async ({ request }: ActionArgs) => {
24+
return redirect("/login");
25+
};
26+
27+
export default function Index() {
28+
const lFetcher = useFetcher();
29+
const pFetcher = useFetcher();
30+
const submit = useSubmit();
31+
const data = new FormData();
32+
data.append("test", "test");
33+
return (
34+
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
35+
<h1>Welcome to Remix</h1>
36+
<button
37+
onClick={() => lFetcher.submit(null, { method: "get", action: "/" })}
38+
>
39+
FETCHER Loader
40+
</button>
41+
<button
42+
onClick={() => pFetcher.submit(data, { method: "POST", action: "/" })}
43+
>
44+
FETCHER Action
45+
</button>
46+
<button onClick={() => submit(null, { method: "POST", action: "/" })}>
47+
SUBMIT Action
48+
</button>
49+
<button onClick={() => submit(data, { method: "PATCH", action: "/" })}>
50+
SUBMIT Action PATCH
51+
</button>
52+
<button onClick={() => submit(null, { method: "DELETE", action: "/" })}>
53+
SUBMIT Action DELETE
54+
</button>
55+
<button onClick={() => submit(null, { method: "PUT", action: "/" })}>
56+
SUBMIT Action PUT
57+
</button>
58+
<div style={{ height: 400, overflowY: "auto", width: 1700 }}>
59+
<EmbeddedDevTools className="!h-[400px] !overflow-y-auto" mainPanelClassName="w-40" />
60+
</div>
61+
<Link to="/login">Login</Link>
62+
<ul>
63+
<li>
64+
<a
65+
target="_blank"
66+
href="https://remix.run/tutorials/blog"
67+
rel="noreferrer"
68+
>
69+
15m Quickstart Blog Tutorial
70+
</a>
71+
</li>
72+
<li>
73+
<a
74+
target="_blank"
75+
href="https://remix.run/tutorials/jokes"
76+
rel="noreferrer"
77+
>
78+
Deep Dive Jokes App Tutorial
79+
</a>
80+
</li>
81+
<li>
82+
<a target="_blank" href="https://remix.run/docs" rel="noreferrer">
83+
Remix Docs
84+
</a>
85+
</li>
86+
</ul>
87+
</div>
88+
);
89+
}

vite.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default defineConfig({
1010
check: true,
1111
include: [
1212
"**/RemixDevTools/RemixDevTools.tsx",
13-
"**/RemixDevTools/index.ts",
13+
"**/RemixDevTools/EmbeddedDevTools.tsx",
1414
"**/src/index.ts",
1515
"**/hooks/useRemixForgeSocket.ts",
1616
"**/tabs/index.tsx",

0 commit comments

Comments
 (0)