Compare commits
11 Commits
jazz-react
...
feat/inspe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebb17e253f | ||
|
|
1ea69dbcc4 | ||
|
|
0fd5ec69d3 | ||
|
|
ed9b863040 | ||
|
|
19de3bb4de | ||
|
|
7b808802c1 | ||
|
|
41f1cbafc3 | ||
|
|
1a98d9e16c | ||
|
|
203584df2d | ||
|
|
29f71d0e30 | ||
|
|
9883eb2c59 |
@@ -16,6 +16,7 @@
|
||||
"clsx": "^2.0.0",
|
||||
"hash-slash": "workspace:*",
|
||||
"jazz-browser-media-images": "workspace:*",
|
||||
"jazz-inspector": "workspace:*",
|
||||
"jazz-react": "workspace:*",
|
||||
"jazz-tools": "workspace:*",
|
||||
"lucide-react": "^0.274.0",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { apiKey } from "@/apiKey.ts";
|
||||
import { getRandomUsername, inIframe, onChatLoad } from "@/util.ts";
|
||||
import { useIframeHashRouter } from "hash-slash";
|
||||
import { JazzInspector } from "jazz-inspector";
|
||||
import { JazzProvider, useAccount } from "jazz-react";
|
||||
import { Group, ID } from "jazz-tools";
|
||||
import { StrictMode } from "react";
|
||||
@@ -61,6 +62,7 @@ createRoot(document.getElementById("root")!).render(
|
||||
defaultProfileName={defaultProfileName}
|
||||
>
|
||||
<App />
|
||||
<JazzInspector />
|
||||
</JazzProvider>
|
||||
</StrictMode>
|
||||
</ThemeProvider>,
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@twind/core": "^1.1.3",
|
||||
"@twind/preset-autoprefix": "^1.0.7",
|
||||
"@twind/preset-tailwind": "^1.1.4",
|
||||
"cojson": "workspace:*",
|
||||
"jazz-react-core": "workspace:*",
|
||||
"jazz-tools": "workspace:*"
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
// Import Twind setup
|
||||
import "./twind.js";
|
||||
|
||||
export { JazzInspector } from "./viewer/new-app.js";
|
||||
|
||||
54
packages/jazz-inspector/src/twind.config.ts
Normal file
54
packages/jazz-inspector/src/twind.config.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { defineConfig } from "@twind/core";
|
||||
import presetAutoprefix from "@twind/preset-autoprefix";
|
||||
import presetTailwind from "@twind/preset-tailwind";
|
||||
|
||||
const stonePalette = {
|
||||
50: "oklch(0.988281 0.002 75)",
|
||||
100: "oklch(0.980563 0.002 75)",
|
||||
200: "oklch(0.917969 0.002 75)",
|
||||
300: "oklch(0.853516 0.002 75)",
|
||||
400: "oklch(0.789063 0.002 75)",
|
||||
500: "oklch(0.726563 0.002 75)",
|
||||
600: "oklch(0.613281 0.002 75)",
|
||||
700: "oklch(0.523438 0.002 75)",
|
||||
800: "oklch(0.412109 0.002 75)",
|
||||
900: "oklch(0.302734 0.002 75)",
|
||||
925: "oklch(0.220000 0.002 75)",
|
||||
950: "oklch(0.193359 0.002 75)",
|
||||
};
|
||||
|
||||
const stonePaletteWithAlpha = { ...stonePalette };
|
||||
|
||||
Object.keys(stonePalette).forEach((key) => {
|
||||
// @ts-ignore
|
||||
stonePaletteWithAlpha[key] = stonePaletteWithAlpha[key].replace(
|
||||
")",
|
||||
"/ <alpha-value>)",
|
||||
);
|
||||
});
|
||||
|
||||
export default defineConfig({
|
||||
presets: [presetAutoprefix(), presetTailwind()],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
stone: stonePaletteWithAlpha,
|
||||
gray: stonePaletteWithAlpha,
|
||||
blue: {
|
||||
50: "#f5f7ff",
|
||||
100: "#ebf0fe",
|
||||
200: "#d6e0fd",
|
||||
300: "#b3c7fc",
|
||||
400: "#8aa6f9",
|
||||
500: "#5870F1",
|
||||
600: "#3651E7",
|
||||
700: "#3313F7",
|
||||
800: "#2A12BE",
|
||||
900: "#12046A",
|
||||
950: "#1e1b4b",
|
||||
DEFAULT: "#3313F7",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
8
packages/jazz-inspector/src/twind.ts
Normal file
8
packages/jazz-inspector/src/twind.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { install, tw } from "@twind/core";
|
||||
import config from "./twind.config";
|
||||
|
||||
// Install Twind globally
|
||||
install(config);
|
||||
|
||||
// Export the tw function for use in components
|
||||
export { tw };
|
||||
@@ -11,41 +11,10 @@ export const Breadcrumbs: React.FC<BreadcrumbsProps> = ({
|
||||
onBreadcrumbClick,
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
zIndex: 20,
|
||||
backgroundColor: "rgba(129, 140, 248, 0.1)", // indigo-400/10 equivalent
|
||||
backdropFilter: "blur(4px)",
|
||||
borderRadius: "0.5rem",
|
||||
display: "inline-flex",
|
||||
paddingLeft: "0.5rem",
|
||||
paddingRight: "0.5rem",
|
||||
paddingTop: "0.25rem",
|
||||
paddingBottom: "0.25rem",
|
||||
whiteSpace: "pre",
|
||||
transition: "all",
|
||||
alignItems: "center",
|
||||
gap: "0.25rem",
|
||||
minHeight: "2.5rem",
|
||||
}}
|
||||
>
|
||||
<div className="relative z-20 bg-blue-400/10 backdrop-blur-sm rounded-lg inline-flex px-2 py-1 whitespace-pre transition-all items-center gap-1 min-h-[2.5rem]">
|
||||
<button
|
||||
onClick={() => onBreadcrumbClick(-1)}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: "0.25rem",
|
||||
borderRadius: "0.125rem",
|
||||
transition: "colors",
|
||||
}}
|
||||
onMouseOver={(e) =>
|
||||
(e.currentTarget.style.backgroundColor = "rgba(99, 102, 241, 0.1)")
|
||||
}
|
||||
onMouseOut={(e) =>
|
||||
(e.currentTarget.style.backgroundColor = "transparent")
|
||||
}
|
||||
className="flex items-center justify-center p-1 rounded-sm transition-colors"
|
||||
aria-label="Go to home"
|
||||
>
|
||||
Start
|
||||
@@ -54,26 +23,16 @@ export const Breadcrumbs: React.FC<BreadcrumbsProps> = ({
|
||||
return (
|
||||
<span
|
||||
key={index}
|
||||
style={{
|
||||
display: "inline-block",
|
||||
paddingLeft: index === 0 ? "0.25rem" : "0",
|
||||
paddingRight: index === path.length - 1 ? "0.25rem" : "0",
|
||||
}}
|
||||
className={`inline-block ${index === 0 ? "pl-1" : "pl-0"} ${
|
||||
index === path.length - 1 ? "pr-1" : "pr-0"
|
||||
}`}
|
||||
>
|
||||
{index === 0 ? null : (
|
||||
<span style={{ color: "rgba(99, 102, 241, 0.3)" }}>{" / "}</span>
|
||||
<span className="text-blue-600/30">{" / "}</span>
|
||||
)}
|
||||
<button
|
||||
onClick={() => onBreadcrumbClick(index)}
|
||||
style={{
|
||||
color: "rgb(67, 56, 202)",
|
||||
}}
|
||||
onMouseOver={(e) =>
|
||||
(e.currentTarget.style.textDecoration = "underline")
|
||||
}
|
||||
onMouseOut={(e) =>
|
||||
(e.currentTarget.style.textDecoration = "none")
|
||||
}
|
||||
className="text-blue hover:underline dark:text-blue-400"
|
||||
>
|
||||
{index === 0 ? page.name || "Root" : page.name}
|
||||
</button>
|
||||
|
||||
@@ -161,7 +161,7 @@ const LabelContentPair = ({
|
||||
content: React.ReactNode;
|
||||
}) => {
|
||||
return (
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: "0.375rem" }}>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<span>{label}</span>
|
||||
<span>{content}</span>
|
||||
</div>
|
||||
@@ -219,34 +219,12 @@ function RenderCoBinaryStream({
|
||||
const sizeInKB = (file.totalSize || 0) / 1024;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
marginTop: "2rem",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "2rem",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(3, 1fr)",
|
||||
gap: "0.5rem",
|
||||
maxWidth: "48rem",
|
||||
}}
|
||||
>
|
||||
<div className="mt-8 flex flex-col gap-8">
|
||||
<div className="grid grid-cols-3 gap-2 max-w-3xl">
|
||||
<LabelContentPair
|
||||
label="Mime Type"
|
||||
content={
|
||||
<span
|
||||
style={{
|
||||
fontFamily: "monospace",
|
||||
backgroundColor: "rgb(243 244 246)",
|
||||
borderRadius: "0.25rem",
|
||||
padding: "0.25rem 0.5rem",
|
||||
fontSize: "0.875rem",
|
||||
}}
|
||||
>
|
||||
<span className="font-mono bg-gray-100 rounded px-2 py-1 text-sm dark:bg-stone-900">
|
||||
{mimeType || "No mime type"}
|
||||
</span>
|
||||
}
|
||||
@@ -275,13 +253,7 @@ function RenderCoBinaryStream({
|
||||
<LabelContentPair
|
||||
label="Preview"
|
||||
content={
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "rgb(249 250 251)",
|
||||
padding: "0.75rem",
|
||||
borderRadius: "0.125rem",
|
||||
}}
|
||||
>
|
||||
<div className="bg-gray-50 dark:bg-gray-925 p-3 rounded">
|
||||
<RenderBlobImage blob={blob} />
|
||||
</div>
|
||||
}
|
||||
@@ -302,30 +274,10 @@ function RenderCoStream({
|
||||
const userCoIds = streamPerUser.map((stream) => stream.split("_session")[0]);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(3, 1fr)",
|
||||
gap: "0.5rem",
|
||||
}}
|
||||
>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{userCoIds.map((id, idx) => (
|
||||
<div
|
||||
style={{
|
||||
padding: "0.75rem",
|
||||
borderRadius: "0.5rem",
|
||||
overflow: "hidden",
|
||||
backgroundColor: "white",
|
||||
border: "1px solid #e5e7eb",
|
||||
cursor: "pointer",
|
||||
boxShadow: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
||||
transition: "background-color 0.2s",
|
||||
}}
|
||||
onMouseOver={(e) =>
|
||||
(e.currentTarget.style.backgroundColor =
|
||||
"rgba(243, 244, 246, 0.05)")
|
||||
}
|
||||
onMouseOut={(e) => (e.currentTarget.style.backgroundColor = "white")}
|
||||
className="p-3 rounded-lg overflow-hidden border border-gray-200 cursor-pointer shadow-sm hover:bg-gray-100/5"
|
||||
key={id}
|
||||
>
|
||||
<AccountOrGroupPreview coId={id as CoID<RawCoValue>} node={node} />
|
||||
|
||||
@@ -16,66 +16,26 @@ export function GridView({
|
||||
const entries = Object.entries(data);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr",
|
||||
gap: "1rem",
|
||||
padding: "0.5rem",
|
||||
}}
|
||||
>
|
||||
<div className="grid grid-cols-1 gap-4 p-2">
|
||||
{entries.map(([key, child], childIndex) => (
|
||||
<div
|
||||
key={childIndex}
|
||||
style={{
|
||||
padding: "0.75rem",
|
||||
borderRadius: "0.5rem",
|
||||
overflow: "hidden",
|
||||
transition: "background-color 0.2s",
|
||||
...(isCoId(child)
|
||||
? {
|
||||
backgroundColor: "white",
|
||||
border: "1px solid #e5e7eb",
|
||||
cursor: "pointer",
|
||||
boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
||||
":hover": {
|
||||
backgroundColor: "rgba(243, 244, 246, 0.05)",
|
||||
},
|
||||
}
|
||||
: {
|
||||
backgroundColor: "rgb(249, 250, 251)",
|
||||
}),
|
||||
}}
|
||||
className={`p-3 rounded-lg overflow-hidden transition-colors ${
|
||||
isCoId(child)
|
||||
? " border border-gray-200 cursor-pointer shadow-sm hover:bg-gray-100/5"
|
||||
: "bg-gray-50 dark:bg-gray-925"
|
||||
}`}
|
||||
onClick={() =>
|
||||
isCoId(child) &&
|
||||
onNavigate([{ coId: child as CoID<RawCoValue>, name: key }])
|
||||
}
|
||||
>
|
||||
<h3
|
||||
style={{
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
}}
|
||||
>
|
||||
<h3 className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
{isCoId(child) ? (
|
||||
<span
|
||||
style={{
|
||||
fontWeight: 500,
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<span className="font-medium flex justify-between">
|
||||
{key}
|
||||
|
||||
<div
|
||||
style={{
|
||||
padding: "0.25rem 0.5rem",
|
||||
fontSize: "0.75rem",
|
||||
backgroundColor: "rgb(243, 244, 246)",
|
||||
borderRadius: "0.25rem",
|
||||
}}
|
||||
>
|
||||
<div className="py-1 px-2 text-xs bg-gray-100 rounded dark:bg-gray-900">
|
||||
<ResolveIcon coId={child as CoID<RawCoValue>} node={node} />
|
||||
</div>
|
||||
</span>
|
||||
@@ -83,7 +43,7 @@ export function GridView({
|
||||
<span>{key}</span>
|
||||
)}
|
||||
</h3>
|
||||
<div style={{ marginTop: "0.5rem", fontSize: "0.875rem" }}>
|
||||
<div className="mt-2 text-sm">
|
||||
{isCoId(child) ? (
|
||||
<CoMapPreview coId={child as CoID<RawCoValue>} node={node} />
|
||||
) : (
|
||||
|
||||
@@ -26,61 +26,24 @@ export function JazzInspector({ position = "right" }: { position?: Position }) {
|
||||
if (coValueId) {
|
||||
setPage(coValueId);
|
||||
}
|
||||
setCoValueId("");
|
||||
};
|
||||
|
||||
const positionStyles = {
|
||||
"bottom right": {
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
},
|
||||
"bottom left": {
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
},
|
||||
"top right": {
|
||||
top: 0,
|
||||
right: 0,
|
||||
},
|
||||
"top left": {
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
right: {
|
||||
right: 0,
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
},
|
||||
left: {
|
||||
left: 0,
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
},
|
||||
const positionClasses = {
|
||||
"bottom right": "bottom-0 right-0",
|
||||
"bottom left": "bottom-0 left-0",
|
||||
"top right": "top-0 right-0",
|
||||
"top left": "top-0 left-0",
|
||||
right: "right-0 top-1/2 -translate-y-1/2",
|
||||
left: "left-0 top-1/2 -translate-y-1/2",
|
||||
};
|
||||
|
||||
if (!open) {
|
||||
return (
|
||||
<button
|
||||
onClick={() => setOpen(true)}
|
||||
style={{
|
||||
position: "fixed",
|
||||
margin: "1rem",
|
||||
backgroundColor: "white",
|
||||
border: "1px solid #e5e7eb",
|
||||
borderRadius: "0.5rem",
|
||||
padding: "0.5rem",
|
||||
boxShadow:
|
||||
"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
|
||||
...positionStyles[position],
|
||||
}}
|
||||
className={`fixed w-10 h-10 inline-block bottom-0 right-0 m-4 bg-white border rounded-md shadow-md p-1.5 ${positionClasses[position]}`}
|
||||
>
|
||||
<svg
|
||||
style={{
|
||||
width: "1.5rem",
|
||||
height: "1.5rem",
|
||||
position: "relative",
|
||||
left: "-1px",
|
||||
top: "1px",
|
||||
}}
|
||||
className="w-full h-auto relative -left-px text-blue"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="119"
|
||||
height="115"
|
||||
@@ -91,35 +54,39 @@ export function JazzInspector({ position = "right" }: { position?: Position }) {
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M118.179 23.8277V0.167999C99.931 7.5527 79.9854 11.6192 59.0897 11.6192C47.1466 11.6192 35.5138 10.2908 24.331 7.7737V30.4076V60.1508C23.2955 59.4385 22.1568 58.8458 20.9405 58.3915C18.1732 57.358 15.128 57.0876 12.1902 57.6145C9.2524 58.1414 6.5539 59.4419 4.4358 61.3516C2.3178 63.2613 0.875401 65.6944 0.291001 68.3433C-0.293399 70.9921 0.00659978 73.7377 1.1528 76.2329C2.2991 78.728 4.2403 80.861 6.7308 82.361C9.2214 83.862 12.1495 84.662 15.1448 84.662C15.6054 84.662 15.8365 84.662 16.0314 84.659C26.5583 84.449 35.042 75.9656 35.2513 65.4386C35.2534 65.3306 35.2544 65.2116 35.2548 65.0486L35.2552 64.7149V64.5521V61.0762V32.1993C43.0533 33.2324 51.0092 33.7656 59.0897 33.7656C59.6696 33.7656 60.2489 33.7629 60.8276 33.7574V89.696C59.792 88.983 58.6533 88.391 57.437 87.936C54.6697 86.903 51.6246 86.632 48.6867 87.159C45.7489 87.686 43.0504 88.987 40.9323 90.896C38.8143 92.806 37.3719 95.239 36.7875 97.888C36.2032 100.537 36.5031 103.283 37.6494 105.778C38.7956 108.273 40.7368 110.405 43.2273 111.906C45.7179 113.406 48.646 114.207 51.6414 114.207C52.1024 114.207 52.3329 114.207 52.5279 114.203C63.0548 113.994 71.5385 105.51 71.7478 94.983C71.7517 94.788 71.7517 94.558 71.7517 94.097V90.621V33.3266C83.962 32.4768 95.837 30.4075 107.255 27.2397V59.9017C106.219 59.1894 105.081 58.5966 103.864 58.1424C101.097 57.1089 98.052 56.8384 95.114 57.3653C92.176 57.8922 89.478 59.1927 87.36 61.1025C85.242 63.0122 83.799 65.4453 83.215 68.0941C82.631 70.743 82.931 73.4886 84.077 75.9837C85.223 78.4789 87.164 80.612 89.655 82.112C92.145 83.612 95.073 84.413 98.069 84.413C98.53 84.413 98.76 84.413 98.955 84.409C109.482 84.2 117.966 75.7164 118.175 65.1895C118.179 64.9945 118.179 64.764 118.179 64.3029V60.8271V23.8277Z"
|
||||
fill="#3313F7"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<span className="sr-only">Open Jazz Inspector</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: "fixed",
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
backgroundColor: "white",
|
||||
borderTop: "1px solid #e5e7eb",
|
||||
padding: "1rem",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: "1rem",
|
||||
}}
|
||||
>
|
||||
<div className="fixed bottom-0 left-0 w-full bg-white border-t border-gray-200 p-4 dark:border-stone-900 dark:bg-stone-925">
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<Breadcrumbs path={path} onBreadcrumbClick={goToIndex} />
|
||||
<button onClick={() => setOpen(false)}>Close</button>
|
||||
<div className="flex-1">
|
||||
<form onSubmit={handleCoValueIdSubmit}>
|
||||
{path.length !== 0 && (
|
||||
<input
|
||||
className="border p-2 rounded-lg min-w-[21rem] font-mono"
|
||||
placeholder="co_z1234567890abcdef123456789"
|
||||
value={coValueId}
|
||||
onChange={(e) =>
|
||||
setCoValueId(e.target.value as CoID<RawCoValue>)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
<button
|
||||
className="ml-auto"
|
||||
type="button"
|
||||
onClick={() => setOpen(false)}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<PageStack
|
||||
@@ -131,80 +98,32 @@ export function JazzInspector({ position = "right" }: { position?: Position }) {
|
||||
<form
|
||||
onSubmit={handleCoValueIdSubmit}
|
||||
aria-hidden={path.length !== 0}
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "0.5rem",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
marginBottom: "5rem",
|
||||
transition: "all 150ms",
|
||||
opacity: path.length > 0 ? 0 : 1,
|
||||
transform:
|
||||
path.length > 0 ? "translateY(-0.5rem) scale(0.95)" : "none",
|
||||
}}
|
||||
className={`flex flex-col justify-center items-center gap-2 h-full w-full mb-20 transition-all duration-150 ${
|
||||
path.length > 0
|
||||
? "opacity-0 translate-y-[-0.5rem] scale-95"
|
||||
: "opacity-100"
|
||||
}`}
|
||||
>
|
||||
<fieldset
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "0.5rem",
|
||||
fontSize: "0.875rem",
|
||||
}}
|
||||
>
|
||||
<h2
|
||||
style={{
|
||||
fontSize: "1.875rem",
|
||||
fontWeight: 500,
|
||||
color: "#030712",
|
||||
textAlign: "center",
|
||||
marginBottom: "1rem",
|
||||
}}
|
||||
>
|
||||
<fieldset className="flex flex-col gap-2 text-sm">
|
||||
<h2 className="text-lg font-medium mb-4 text-stone-900 dark:text-white">
|
||||
Jazz CoValue Inspector
|
||||
</h2>
|
||||
<input
|
||||
style={{
|
||||
border: "1px solid #e5e7eb",
|
||||
padding: "1rem",
|
||||
borderRadius: "0.5rem",
|
||||
minWidth: "21rem",
|
||||
fontFamily: "monospace",
|
||||
}}
|
||||
className="border border-gray-200 p-4 rounded-lg min-w-[21rem] font-mono"
|
||||
placeholder="co_z1234567890abcdef123456789"
|
||||
value={coValueId}
|
||||
onChange={(e) => setCoValueId(e.target.value as CoID<RawCoValue>)}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
style={{
|
||||
backgroundColor: "rgb(99 102 241)",
|
||||
color: "white",
|
||||
padding: "0.5rem 1rem",
|
||||
borderRadius: "0.375rem",
|
||||
}}
|
||||
onMouseOver={(e) =>
|
||||
(e.currentTarget.style.backgroundColor =
|
||||
"rgba(99 102 241, 0.8)")
|
||||
}
|
||||
onMouseOut={(e) =>
|
||||
(e.currentTarget.style.backgroundColor = "rgb(99 102 241)")
|
||||
}
|
||||
className="bg-blue text-white py-2 px-4 rounded-md hover:bg-blue-800"
|
||||
>
|
||||
Inspect
|
||||
</button>
|
||||
<hr />
|
||||
<button
|
||||
type="button"
|
||||
style={{
|
||||
border: "1px solid #e5e7eb",
|
||||
display: "inline-block",
|
||||
padding: "0.375rem 0.5rem",
|
||||
color: "black",
|
||||
borderRadius: "0.375rem",
|
||||
}}
|
||||
className="border border-gray-200 inline-block py-1.5 px-2 rounded-md"
|
||||
onClick={() => {
|
||||
setCoValueId(me._raw.id);
|
||||
setPage(me._raw.id);
|
||||
|
||||
@@ -27,28 +27,8 @@ export function PageStack({
|
||||
const index = path.length - 1;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
marginTop: "1rem",
|
||||
height: "40vh",
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
{children && (
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
paddingBottom: "5rem",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
<div className="relative mt-4 h-[40vh] overflow-y-auto">
|
||||
{children && <div className="absolute inset-0 pb-20">{children}</div>}
|
||||
{node && page && (
|
||||
<Page
|
||||
coId={page.coId}
|
||||
@@ -57,15 +37,13 @@ export function PageStack({
|
||||
onHeaderClick={goBack}
|
||||
onNavigate={addPages}
|
||||
isTopLevel={index === path.length - 1}
|
||||
className="transition-transform transition-opacity duration-300 ease-out"
|
||||
style={{
|
||||
transform: `translateZ(${(index - path.length + 1) * 200}px) scale(${
|
||||
1 - (path.length - index - 1) * 0.05
|
||||
}) translateY(${-(index - path.length + 1) * -4}%)`,
|
||||
opacity: 1 - (path.length - index - 1) * 0.05,
|
||||
zIndex: index,
|
||||
transitionProperty: "transform, opacity",
|
||||
transitionDuration: "0.3s",
|
||||
transitionTimingFunction: "ease-out",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -16,6 +16,7 @@ type PageProps = {
|
||||
onHeaderClick?: () => void;
|
||||
isTopLevel?: boolean;
|
||||
style: React.CSSProperties;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export function Page({
|
||||
@@ -25,6 +26,7 @@ export function Page({
|
||||
onNavigate,
|
||||
onHeaderClick,
|
||||
style,
|
||||
className = "",
|
||||
isTopLevel,
|
||||
}: PageProps) {
|
||||
const { value, snapshot, type, extendedType } = useResolvedCoValue(
|
||||
@@ -52,31 +54,15 @@ export function Page({
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
zIndex: 1,
|
||||
inset: 0,
|
||||
backgroundColor: "white",
|
||||
borderWidth: "1px",
|
||||
borderColor: "rgba(0, 0, 0, 0.05)",
|
||||
borderRadius: "0.75rem",
|
||||
boxShadow:
|
||||
"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
|
||||
padding: "1.5rem",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
backgroundClip: "padding-box",
|
||||
}}
|
||||
style={style}
|
||||
className={
|
||||
className +
|
||||
" absolute z-10 inset-0 border rounded-xl shadow-lg p-6 w-full h-full bg-clip-padding"
|
||||
}
|
||||
>
|
||||
{!isTopLevel && (
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
height: "2.5rem",
|
||||
}}
|
||||
className="absolute left-0 right-0 top-0 h-10"
|
||||
aria-label="Back"
|
||||
onClick={() => {
|
||||
onHeaderClick?.();
|
||||
@@ -84,72 +70,30 @@ export function Page({
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: "1rem",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}
|
||||
>
|
||||
<h2
|
||||
style={{
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: "700",
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
flexDirection: "column",
|
||||
gap: "0.25rem",
|
||||
}}
|
||||
>
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-2xl font-bold flex flex-col items-start gap-1">
|
||||
<span>
|
||||
{name}
|
||||
{typeof snapshot === "object" && "name" in snapshot ? (
|
||||
<span style={{ color: "rgb(75, 85, 99)", fontWeight: "500" }}>
|
||||
<span className="text-gray-600 font-medium">
|
||||
{" "}
|
||||
{(snapshot as { name: string }).name}
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
</h2>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
||||
<span
|
||||
style={{
|
||||
fontSize: "0.75rem",
|
||||
color: "rgb(55, 65, 81)",
|
||||
fontWeight: "500",
|
||||
padding: "0.125rem 0.25rem",
|
||||
marginLeft: "-0.125rem",
|
||||
borderRadius: "0.25rem",
|
||||
backgroundColor: "rgba(55, 65, 81, 0.05)",
|
||||
display: "inline-block",
|
||||
fontFamily: "monospace",
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs text-gray-700 font-medium py-0.5 px-1 -ml-0.5 rounded bg-gray-700/5 inline-block font-mono">
|
||||
{type && <TypeIcon type={type} extendedType={extendedType} />}
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
fontSize: "0.75rem",
|
||||
color: "rgb(55, 65, 81)",
|
||||
fontWeight: "500",
|
||||
padding: "0.125rem 0.25rem",
|
||||
marginLeft: "-0.125rem",
|
||||
borderRadius: "0.25rem",
|
||||
backgroundColor: "rgba(55, 65, 81, 0.05)",
|
||||
display: "inline-block",
|
||||
fontFamily: "monospace",
|
||||
}}
|
||||
>
|
||||
<span className="text-xs text-gray-700 font-medium py-0.5 px-1 -ml-0.5 rounded bg-gray-700/5 inline-block font-mono">
|
||||
{coId}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ overflow: "auto", maxHeight: "calc(100% - 4rem)" }}>
|
||||
<div className="overflow-auto max-h-[calc(100%-4rem)]">
|
||||
{type === "costream" ? (
|
||||
<CoStreamView
|
||||
data={snapshot}
|
||||
@@ -163,13 +107,7 @@ export function Page({
|
||||
<TableView data={snapshot} node={node} onNavigate={onNavigate} />
|
||||
)}
|
||||
{extendedType !== "account" && extendedType !== "group" && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: "0.75rem",
|
||||
color: "rgb(107, 114, 128)",
|
||||
marginTop: "1rem",
|
||||
}}
|
||||
>
|
||||
<div className="text-xs text-gray-500 mt-4">
|
||||
Owned by{" "}
|
||||
<AccountOrGroupPreview
|
||||
coId={value.group.id}
|
||||
|
||||
@@ -51,45 +51,23 @@ export function TableView({
|
||||
|
||||
return (
|
||||
<div>
|
||||
<table
|
||||
style={{
|
||||
minWidth: "100%",
|
||||
borderSpacing: 0,
|
||||
borderCollapse: "collapse",
|
||||
}}
|
||||
>
|
||||
<thead
|
||||
style={{
|
||||
position: "sticky",
|
||||
top: 0,
|
||||
borderBottom: "1px solid #e5e7eb",
|
||||
}}
|
||||
>
|
||||
<table className="min-w-full border-spacing-0 border-collapse">
|
||||
<thead className="sticky top-0 border-b border-gray-200">
|
||||
<tr>
|
||||
{["", ...keys].map((key) => (
|
||||
<th
|
||||
key={key}
|
||||
style={{
|
||||
padding: "0.75rem 1rem",
|
||||
backgroundColor: "#f9fafb",
|
||||
textAlign: "left",
|
||||
fontSize: "0.75rem",
|
||||
fontWeight: 500,
|
||||
color: "#6b7280",
|
||||
borderRadius: "0.25rem",
|
||||
}}
|
||||
className="p-3 bg-gray-50 dark:bg-gray-925 text-left text-xs font-medium text-gray-500 rounded"
|
||||
>
|
||||
{key}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
style={{ backgroundColor: "white", borderTop: "1px solid #e5e7eb" }}
|
||||
>
|
||||
<tbody className=" border-t border-gray-200">
|
||||
{resolvedRows.slice(0, visibleRowsCount).map((item, index) => (
|
||||
<tr key={index}>
|
||||
<td style={{ padding: "0.25rem 0.25rem" }}>
|
||||
<td className="p-1">
|
||||
<button
|
||||
onClick={() =>
|
||||
onNavigate([
|
||||
@@ -99,21 +77,7 @@ export function TableView({
|
||||
},
|
||||
])
|
||||
}
|
||||
style={{
|
||||
padding: "1rem",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: "0.875rem",
|
||||
color: "#6b7280",
|
||||
borderRadius: "0.25rem",
|
||||
}}
|
||||
onMouseOver={(e) => {
|
||||
e.currentTarget.style.backgroundColor = "#f3f4f6";
|
||||
e.currentTarget.style.color = "#3b82f6";
|
||||
}}
|
||||
onMouseOut={(e) => {
|
||||
e.currentTarget.style.backgroundColor = "transparent";
|
||||
e.currentTarget.style.color = "#6b7280";
|
||||
}}
|
||||
className="p-4 whitespace-nowrap text-sm text-gray-500 rounded hover:bg-gray-100 hover:text-blue-500"
|
||||
>
|
||||
<LinkIcon />
|
||||
</button>
|
||||
@@ -121,12 +85,7 @@ export function TableView({
|
||||
{keys.map((key) => (
|
||||
<td
|
||||
key={key}
|
||||
style={{
|
||||
padding: "1rem",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: "0.875rem",
|
||||
color: "#6b7280",
|
||||
}}
|
||||
className="p-4 whitespace-nowrap text-sm text-gray-500"
|
||||
>
|
||||
<ValueRenderer
|
||||
json={(item.snapshot as JsonObject)[key]}
|
||||
@@ -153,38 +112,18 @@ export function TableView({
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div
|
||||
style={{
|
||||
padding: "1rem 0",
|
||||
color: "#6b7280",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: "0.5rem",
|
||||
}}
|
||||
>
|
||||
<div className="py-4 text-gray-500 flex items-center justify-between gap-2">
|
||||
<span>
|
||||
Showing {Math.min(visibleRowsCount, coIdArray.length)} of{" "}
|
||||
{coIdArray.length}
|
||||
</span>
|
||||
{hasMore && (
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<div className="text-center">
|
||||
<button
|
||||
onClick={loadMore}
|
||||
style={{
|
||||
padding: "0.5rem 1rem",
|
||||
backgroundColor: "#3b82f6",
|
||||
color: "white",
|
||||
borderRadius: "0.25rem",
|
||||
}}
|
||||
onMouseOver={(e) => {
|
||||
e.currentTarget.style.backgroundColor = "#2563eb";
|
||||
}}
|
||||
onMouseOut={(e) => {
|
||||
e.currentTarget.style.backgroundColor = "#3b82f6";
|
||||
}}
|
||||
className="px-4 py-2 bg-blue text-white rounded hover:bg-blue-800"
|
||||
>
|
||||
Load More
|
||||
Load more
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -25,7 +25,7 @@ export const TypeIcon = ({
|
||||
const iconKey = extendedType || type;
|
||||
const icon = iconMap[iconKey as keyof typeof iconMap];
|
||||
|
||||
return icon ? <span style={{ fontFamily: "monospace" }}>{icon}</span> : null;
|
||||
return icon ? <span className="font-mono">{icon}</span> : null;
|
||||
};
|
||||
|
||||
export const ResolveIcon = ({
|
||||
@@ -38,17 +38,10 @@ export const ResolveIcon = ({
|
||||
const { type, extendedType, snapshot } = useResolvedCoValue(coId, node);
|
||||
|
||||
if (snapshot === "unavailable" && !type) {
|
||||
return <div style={{ color: "#4B5563", fontWeight: 500 }}>Unavailable</div>;
|
||||
return <div className="text-gray-600 font-medium">Unavailable</div>;
|
||||
}
|
||||
|
||||
if (!type)
|
||||
return (
|
||||
<div
|
||||
style={{ whiteSpace: "pre", width: "3.5rem", fontFamily: "monospace" }}
|
||||
>
|
||||
{" "}
|
||||
</div>
|
||||
);
|
||||
if (!type) return <div className="whitespace-pre w-14 font-mono"> </div>;
|
||||
|
||||
return <TypeIcon type={type} extendedType={extendedType} />;
|
||||
};
|
||||
|
||||
@@ -17,32 +17,24 @@ export function ValueRenderer({
|
||||
compact?: boolean;
|
||||
onCoIDClick?: (childNode: CoID<RawCoValue>) => void;
|
||||
}) {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
|
||||
if (typeof json === "undefined" || json === undefined) {
|
||||
return <span style={{ color: "#9CA3AF" }}>undefined</span>;
|
||||
return <span className="text-gray-400">undefined</span>;
|
||||
}
|
||||
|
||||
if (json === null) {
|
||||
return <span style={{ color: "#9CA3AF" }}>null</span>;
|
||||
return <span className="text-gray-400">null</span>;
|
||||
}
|
||||
|
||||
if (typeof json === "string" && json.startsWith("co_")) {
|
||||
const linkStyle = onCoIDClick
|
||||
? {
|
||||
color: "#3B82F6",
|
||||
cursor: "pointer",
|
||||
display: "inline-flex",
|
||||
gap: "0.25rem",
|
||||
alignItems: "center",
|
||||
}
|
||||
: {
|
||||
display: "inline-flex",
|
||||
gap: "0.25rem",
|
||||
alignItems: "center",
|
||||
};
|
||||
const linkClasses = onCoIDClick
|
||||
? "text-blue-500 cursor-pointer inline-flex gap-1 items-center"
|
||||
: "inline-flex gap-1 items-center";
|
||||
|
||||
return (
|
||||
<span
|
||||
style={linkStyle}
|
||||
className={linkClasses}
|
||||
onClick={() => {
|
||||
onCoIDClick?.(json as CoID<RawCoValue>);
|
||||
}}
|
||||
@@ -55,33 +47,22 @@ export function ValueRenderer({
|
||||
|
||||
if (typeof json === "string") {
|
||||
return (
|
||||
<span style={{ color: "#064E3B", fontFamily: "monospace" }}>{json}</span>
|
||||
<span className="text-teal-900 font-mono dark:text-teal-200">{json}</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof json === "number") {
|
||||
return <span style={{ color: "#A855F7" }}>{json}</span>;
|
||||
return <span className="text-purple-500 dark:text-purple-200">{json}</span>;
|
||||
}
|
||||
|
||||
if (typeof json === "boolean") {
|
||||
const booleanStyle = {
|
||||
color: json ? "#15803D" : "#B45309",
|
||||
backgroundColor: json
|
||||
? "rgba(34, 197, 94, 0.05)"
|
||||
: "rgba(245, 158, 11, 0.05)",
|
||||
fontFamily: "monospace",
|
||||
display: "inline-block",
|
||||
padding: "0.125rem 0.25rem",
|
||||
borderRadius: "0.25rem",
|
||||
};
|
||||
|
||||
return <span style={booleanStyle}>{json.toString()}</span>;
|
||||
}
|
||||
|
||||
if (Array.isArray(json)) {
|
||||
return (
|
||||
<span title={JSON.stringify(json)}>
|
||||
Array <span style={{ color: "#6B7280" }}>({json.length})</span>
|
||||
<span
|
||||
className={`inline-block py-0.5 px-1 rounded ${
|
||||
json ? "text-green-700 bg-green-50" : "text-amber-700 bg-amber-50"
|
||||
} font-mono`}
|
||||
>
|
||||
{json.toString()}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -90,23 +71,31 @@ export function ValueRenderer({
|
||||
return (
|
||||
<span
|
||||
title={JSON.stringify(json, null, 2)}
|
||||
style={{
|
||||
display: "inline-block",
|
||||
maxWidth: "16rem",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
}}
|
||||
className="inline-block max-w-64"
|
||||
>
|
||||
{compact ? (
|
||||
<span>
|
||||
Object{" "}
|
||||
<span style={{ color: "#6B7280" }}>
|
||||
({Object.keys(json).length})
|
||||
</span>
|
||||
<span className="text-gray-500">({Object.keys(json).length})</span>
|
||||
<pre className="mt-1 text-sm whitespace-pre-wrap">
|
||||
{isExpanded
|
||||
? JSON.stringify(json, null, 2)
|
||||
: JSON.stringify(json, null, 2)
|
||||
.split("\n")
|
||||
.slice(0, 3)
|
||||
.join("\n") + (Object.keys(json).length > 2 ? "\n..." : "")}
|
||||
</pre>
|
||||
<button
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
className="text-xs text-gray-500 hover:text-gray-700"
|
||||
>
|
||||
{isExpanded ? "Show less" : "Show more"}
|
||||
</button>
|
||||
</span>
|
||||
) : (
|
||||
JSON.stringify(json, null, 2)
|
||||
<pre className="whitespace-pre-wrap">
|
||||
{JSON.stringify(json, null, 2)}
|
||||
</pre>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
@@ -131,22 +120,14 @@ export const CoMapPreview = ({
|
||||
|
||||
if (!snapshot) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
borderRadius: "0.25rem",
|
||||
backgroundColor: "#F3F4F6",
|
||||
animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",
|
||||
whiteSpace: "pre",
|
||||
width: "6rem",
|
||||
}}
|
||||
>
|
||||
<div className="rounded bg-gray-100 animate-pulse whitespace-pre w-24">
|
||||
{" "}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (snapshot === "unavailable" && !value) {
|
||||
return <div style={{ color: "#6B7280" }}>Unavailable</div>;
|
||||
return <div className="text-gray-500">Unavailable</div>;
|
||||
}
|
||||
|
||||
if (extendedType === "image" && isBrowserImage(snapshot)) {
|
||||
@@ -154,16 +135,9 @@ export const CoMapPreview = ({
|
||||
<div>
|
||||
<img
|
||||
src={snapshot.placeholderDataURL}
|
||||
style={{
|
||||
width: "2rem",
|
||||
height: "2rem",
|
||||
border: "2px solid white",
|
||||
boxShadow:
|
||||
"0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
|
||||
margin: "0.5rem 0",
|
||||
}}
|
||||
className="w-8 h-8 border-2 border-white shadow my-2"
|
||||
/>
|
||||
<span style={{ color: "#6B7280", fontSize: "0.875rem" }}>
|
||||
<span className="text-gray-500 text-sm">
|
||||
{snapshot.originalSize[0]} x {snapshot.originalSize[1]}
|
||||
</span>
|
||||
</div>
|
||||
@@ -174,9 +148,7 @@ export const CoMapPreview = ({
|
||||
return (
|
||||
<div>
|
||||
Record{" "}
|
||||
<span style={{ color: "#6B7280" }}>
|
||||
({Object.keys(snapshot).length})
|
||||
</span>
|
||||
<span className="text-gray-500">({Object.keys(snapshot).length})</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -185,7 +157,7 @@ export const CoMapPreview = ({
|
||||
return (
|
||||
<div>
|
||||
List{" "}
|
||||
<span style={{ color: "#6B7280" }}>
|
||||
<span className="text-gray-500">
|
||||
({(snapshot as unknown as []).length})
|
||||
</span>
|
||||
</div>
|
||||
@@ -193,19 +165,13 @@ export const CoMapPreview = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "auto 1fr",
|
||||
gap: "0.5rem",
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="grid grid-cols-[auto_1fr] gap-2">
|
||||
{Object.entries(snapshot)
|
||||
.slice(0, limit)
|
||||
.map(([key, value]) => (
|
||||
<React.Fragment key={key}>
|
||||
<span style={{ fontWeight: "bold" }}>{key}: </span>
|
||||
<span className="font-bold">{key}: </span>
|
||||
<span>
|
||||
<ValueRenderer json={value} />
|
||||
</span>
|
||||
@@ -213,9 +179,7 @@ export const CoMapPreview = ({
|
||||
))}
|
||||
</div>
|
||||
{Object.entries(snapshot).length > limit && (
|
||||
<div
|
||||
style={{ textAlign: "left", fontSize: "0.875rem", color: "#6B7280" }}
|
||||
>
|
||||
<div className="text-left text-sm text-gray-500">
|
||||
{Object.entries(snapshot).length - limit} more
|
||||
</div>
|
||||
)}
|
||||
@@ -262,18 +226,13 @@ export function AccountOrGroupPreview({
|
||||
const displayName = extendedType === "account" ? name || "Account" : "Group";
|
||||
const displayText = showId ? `${displayName} (${coId})` : displayName;
|
||||
|
||||
const props = onClick
|
||||
? {
|
||||
onClick: () => onClick(displayName),
|
||||
style: {
|
||||
color: "#3B82F6",
|
||||
cursor: "pointer",
|
||||
textDecoration: "underline",
|
||||
},
|
||||
}
|
||||
: {
|
||||
style: { color: "#6B7280" },
|
||||
};
|
||||
const className = onClick
|
||||
? "text-blue cursor-pointer underline dark:text-blue-400"
|
||||
: "text-gray-500";
|
||||
|
||||
return <span {...props}>{displayText}</span>;
|
||||
return (
|
||||
<span className={className} onClick={() => onClick?.(displayName)}>
|
||||
{displayText}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export default defineConfig({
|
||||
entry: path.resolve(__dirname, "src/app.tsx"),
|
||||
name: "JazzInspector",
|
||||
// the proper extensions will be added
|
||||
fileName: "jazz-inspector",
|
||||
fileName: "app",
|
||||
formats: ["es"],
|
||||
},
|
||||
},
|
||||
|
||||
65
pnpm-lock.yaml
generated
65
pnpm-lock.yaml
generated
@@ -67,6 +67,9 @@ importers:
|
||||
jazz-browser-media-images:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/jazz-browser-media-images
|
||||
jazz-inspector:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/jazz-inspector
|
||||
jazz-react:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/jazz-react
|
||||
@@ -1712,6 +1715,15 @@ importers:
|
||||
|
||||
packages/jazz-inspector:
|
||||
dependencies:
|
||||
'@twind/core':
|
||||
specifier: ^1.1.3
|
||||
version: 1.1.3(typescript@5.6.3)
|
||||
'@twind/preset-autoprefix':
|
||||
specifier: ^1.0.7
|
||||
version: 1.0.7(@twind/core@1.1.3(typescript@5.6.3))(typescript@5.6.3)
|
||||
'@twind/preset-tailwind':
|
||||
specifier: ^1.1.4
|
||||
version: 1.1.4(@twind/core@1.1.3(typescript@5.6.3))(typescript@5.6.3)
|
||||
cojson:
|
||||
specifier: workspace:*
|
||||
version: link:../cojson
|
||||
@@ -5238,6 +5250,35 @@ packages:
|
||||
'@tsconfig/node22@22.0.0':
|
||||
resolution: {integrity: sha512-twLQ77zevtxobBOD4ToAtVmuYrpeYUh3qh+TEp+08IWhpsrIflVHqQ1F1CiPxQGL7doCdBIOOCF+1Tm833faNg==}
|
||||
|
||||
'@twind/core@1.1.3':
|
||||
resolution: {integrity: sha512-/B/aNFerMb2IeyjSJy3SJxqVxhrT77gBDknLMiZqXIRr4vNJqiuhx7KqUSRzDCwUmyGuogkamz+aOLzN6MeSLw==}
|
||||
engines: {node: '>=14.15.0'}
|
||||
peerDependencies:
|
||||
typescript: ^4.8.4
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@twind/preset-autoprefix@1.0.7':
|
||||
resolution: {integrity: sha512-3wmHO0pG/CVxYBNZUV0tWcL7CP0wD5KpyWAQE/KOalWmOVBj+nH6j3v6Y3I3pRuMFaG5DC78qbYbhA1O11uG3w==}
|
||||
engines: {node: '>=14.15.0'}
|
||||
peerDependencies:
|
||||
'@twind/core': ^1.1.0
|
||||
typescript: ^4.8.4
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@twind/preset-tailwind@1.1.4':
|
||||
resolution: {integrity: sha512-zv85wrP/DW4AxgWrLfH7kyGn/KJF3K04FMLVl2AjoxZGYdCaoZDkL8ma3hzaKQ+WGgBFRubuB/Ku2Rtv/wjzVw==}
|
||||
engines: {node: '>=14.15.0'}
|
||||
peerDependencies:
|
||||
'@twind/core': ^1.1.0
|
||||
typescript: ^4.8.4
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@types/argparse@1.0.38':
|
||||
resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==}
|
||||
|
||||
@@ -10833,6 +10874,9 @@ packages:
|
||||
structured-headers@0.4.1:
|
||||
resolution: {integrity: sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==}
|
||||
|
||||
style-vendorizer@2.2.3:
|
||||
resolution: {integrity: sha512-/VDRsWvQAgspVy9eATN3z6itKTuyg+jW1q6UoTCQCFRqPDw8bi3E1hXIKnGw5LvXS2AQPuJ7Af4auTLYeBOLEg==}
|
||||
|
||||
styleq@0.1.3:
|
||||
resolution: {integrity: sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA==}
|
||||
|
||||
@@ -15440,6 +15484,25 @@ snapshots:
|
||||
|
||||
'@tsconfig/node22@22.0.0': {}
|
||||
|
||||
'@twind/core@1.1.3(typescript@5.6.3)':
|
||||
dependencies:
|
||||
csstype: 3.1.3
|
||||
optionalDependencies:
|
||||
typescript: 5.6.3
|
||||
|
||||
'@twind/preset-autoprefix@1.0.7(@twind/core@1.1.3(typescript@5.6.3))(typescript@5.6.3)':
|
||||
dependencies:
|
||||
'@twind/core': 1.1.3(typescript@5.6.3)
|
||||
style-vendorizer: 2.2.3
|
||||
optionalDependencies:
|
||||
typescript: 5.6.3
|
||||
|
||||
'@twind/preset-tailwind@1.1.4(@twind/core@1.1.3(typescript@5.6.3))(typescript@5.6.3)':
|
||||
dependencies:
|
||||
'@twind/core': 1.1.3(typescript@5.6.3)
|
||||
optionalDependencies:
|
||||
typescript: 5.6.3
|
||||
|
||||
'@types/argparse@1.0.38': {}
|
||||
|
||||
'@types/aria-query@5.0.4': {}
|
||||
@@ -21733,6 +21796,8 @@ snapshots:
|
||||
|
||||
structured-headers@0.4.1: {}
|
||||
|
||||
style-vendorizer@2.2.3: {}
|
||||
|
||||
styleq@0.1.3: {}
|
||||
|
||||
stylis@4.2.0: {}
|
||||
|
||||
Reference in New Issue
Block a user