Skip to content

Commit

Permalink
feat: data type viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
stanley2058 committed Feb 25, 2025
1 parent e8a9219 commit 4f7bdcb
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 18 deletions.
67 changes: 52 additions & 15 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from "react";
import { useEffect, useMemo } from "react";
import { JsonViewer } from "@textea/json-viewer";
import { Sidebar } from "./components/sidebar";
import { Input } from "@/components/ui/input";
Expand All @@ -20,21 +20,17 @@ export default function App() {
if (apiVersion === "v1") Y.applyUpdate(ydoc, buf);
if (apiVersion === "v2") Y.applyUpdateV2(ydoc, buf);
}
displayOptionStore.setState({ display: ydoc });
displayOptionStore.setState({ display: ydoc, displayError: null });
// @ts-expect-error expose ydoc for advance debug
window.currentDoc = ydoc;
} catch (e) {
displayOptionStore.setState({ display: e });
// @ts-expect-error expose ydoc for advance debug
window.currentDoc = null;
ydoc.destroy();
displayOptionStore.setState({ display: null, displayError: e });
}

if (
typeof prev === "object" &&
prev &&
"destroy" in prev &&
typeof prev.destroy === "function"
) {
prev.destroy();
}
if (prev && prev.destroy) prev.destroy();
}, [inputBuffer, apiVersion]);

return (
Expand All @@ -50,17 +46,19 @@ export default function App() {
}
className="mb-4 bg-gray-800 text-white border-gray-700"
/>
<div className="flex-1 overflow-auto bg-gray-800 rounded-lg p-4 [&>div]:px-4 [&>div]:py-2">
<Viewer />
<div className="flex-1 gap-4 grid grid-cols-2 overflow-auto bg-gray-800 rounded-lg p-4 [&>div]:px-4 [&>div]:py-2">
<MainViewer />
<SideViewer />
</div>
</main>
</div>
);
}

function Viewer() {
function MainViewer() {
const {
display,
displayError,
indentWidth,
enableClipboard,
displaySize,
Expand All @@ -69,7 +67,46 @@ function Viewer() {
return (
<JsonViewer
theme="dark"
value={display}
value={displayError ?? display}
indentWidth={indentWidth}
enableClipboard={enableClipboard}
displayDataTypes={displayDataTypes}
displaySize={displaySize}
defaultInspectDepth={3}
/>
);
}

function SideViewer() {
const {
display,
displayError,
indentWidth,
enableClipboard,
displaySize,
displayDataTypes,
} = useStore(displayOptionStore);
const getApiType = useStore(yDocOptionStore, (s) => s.getApiType);
const contentDisplay = useMemo(() => {
if (!display) return null;
try {
const ydoc = new Y.Doc();
Y.applyUpdateV2(ydoc, Y.encodeStateAsUpdateV2(display));
const displayObj: Record<string, unknown> = {};
for (const key of ydoc.share.keys()) {
displayObj[key] = ydoc[getApiType](key);
}
ydoc.destroy();
return displayObj;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return null;
}
}, [display, getApiType]);
return (
<JsonViewer
theme="dark"
value={displayError ?? contentDisplay}
indentWidth={indentWidth}
enableClipboard={enableClipboard}
displayDataTypes={displayDataTypes}
Expand Down
33 changes: 31 additions & 2 deletions src/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { useStore } from "zustand";
import { displayOptionStore, yDocOptionStore } from "@/lib/store";
import {
displayOptionStore,
GetApi,
getApis,
yDocOptionStore,
} from "@/lib/store";

export function Sidebar() {
return (
Expand All @@ -16,7 +21,7 @@ export function Sidebar() {
}

function YDocOptions() {
const { apiVersion } = useStore(yDocOptionStore);
const { apiVersion, getApiType } = useStore(yDocOptionStore);
return (
<>
<h3 className="text-lg font-semibold mt-2">Y.Doc Options</h3>
Expand Down Expand Up @@ -51,6 +56,30 @@ function YDocOptions() {
</div>
</RadioGroup>
</div>

<h4 className="text-sm font-semibold">View Data As</h4>
<div className="flex items-center space-x-2">
<RadioGroup
value={`option-${getApiType}`}
onValueChange={(v) =>
yDocOptionStore.setState({
getApiType: v.split("-")[1] as GetApi,
})
}
>
{getApis.map((k) => (
<div key={k} className="flex items-center">
<Label
htmlFor={`option-${k}`}
className="cursor-pointer flex gap-2 justify-center items-center"
>
<RadioGroupItem value={`option-${k}`} id={`option-${k}`} />
<code>{k}</code>
</Label>
</div>
))}
</RadioGroup>
</div>
</>
);
}
Expand Down
16 changes: 15 additions & 1 deletion src/lib/store.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import { createStore } from "zustand";
import { persist } from "zustand/middleware";
import type * as Y from "yjs";

export const getApis = [
"getArray",
"getMap",
"getText",
"getXmlElement",
"getXmlFragment",
] as const;
export type GetApi = (typeof getApis)[number];

interface DisplayOptionStore {
display: unknown;
display: Y.Doc | null;
displayError: unknown;
indentWidth: number;
enableClipboard: boolean;
displayDataTypes: boolean;
Expand All @@ -12,12 +23,14 @@ interface DisplayOptionStore {
interface YDocOptionStore {
inputBuffer: string;
apiVersion: "v1" | "v2";
getApiType: GetApi;
}

export const displayOptionStore = createStore<DisplayOptionStore>()(
persist<DisplayOptionStore>(
() => ({
display: null,
displayError: null,
indentWidth: 4,
enableClipboard: true,
displayDataTypes: false,
Expand All @@ -34,6 +47,7 @@ export const yDocOptionStore = createStore<YDocOptionStore>()(
() => ({
inputBuffer: "",
apiVersion: "v1",
getApiType: "getArray",
}),
{ name: "ydoc-inspector-ydoc-option" },
),
Expand Down

0 comments on commit 4f7bdcb

Please sign in to comment.