@dugongjs/cli
Version:
63 lines (62 loc) • 2.76 kB
JavaScript
import chalk from "chalk";
import { Box, Text, useInput } from "ink";
import React from "react";
export const JSONViewer = ({ data, width, height, isFocused }) => {
const [offset, setOffset] = React.useState(0);
React.useEffect(() => setOffset(0), [data, width, height]);
const lines = React.useMemo(() => {
if (!data)
return ["—"];
const pretty = JSON.stringify(data, null, 2) ?? "";
const raw = pretty.split("\n");
const wrapped = wrapLines(raw, width);
return wrapped.map(colorizeLine);
}, [data, width]);
const maxOffset = Math.max(0, lines.length - height);
React.useEffect(() => {
setOffset((o) => Math.min(Math.max(0, o), maxOffset));
}, [maxOffset]);
useInput((input, key) => {
if (!isFocused)
return;
if (key.upArrow || input === "k")
setOffset((o) => Math.max(0, o - 1));
if (key.downArrow || input === "j")
setOffset((o) => Math.min(maxOffset, o + 1));
if (key.pageUp)
setOffset((o) => Math.max(0, o - Math.max(1, height - 1)));
if (key.pageDown)
setOffset((o) => Math.min(maxOffset, o + Math.max(1, height - 1)));
}, { isActive: isFocused });
const windowed = lines.slice(offset, offset + height);
return (React.createElement(React.Fragment, null,
React.createElement(Box, { flexDirection: "column", width: width }, windowed.length === 0 ? (React.createElement(Text, { color: "gray", wrap: "truncate" }, "\u2014")) : (windowed.map((line, i) => (React.createElement(Text, { key: `${offset}-${i}`, wrap: "truncate" }, line))))),
React.createElement(Box, { width: width, marginTop: 0 },
React.createElement(Text, { color: "gray", dimColor: true, wrap: "truncate" }, lines.length > 0
? `${Math.min(lines.length, offset + 1)}-${Math.min(lines.length, offset + height)} / ${lines.length}`
: ""))));
};
function wrapLines(lines, width) {
if (width <= 0)
return lines;
const out = [];
for (const line of lines) {
if (line.length <= width) {
out.push(line);
continue;
}
let start = 0;
while (start < line.length) {
out.push(line.slice(start, start + width));
start += width;
}
}
return out;
}
function colorizeLine(line) {
let s = line.replace(/("([^"\\]|\\.)*")\s*:/g, (m) => chalk.cyan(m));
s = s.replace(/:\s*("([^"\\]|\\.)*")/g, (_, g1) => `: ${chalk.green(g1)}`);
s = s.replace(/:\s*(-?\d+(?:\.\d+)?(?:e[+-]?\d+)?)/gi, (_, num) => `: ${chalk.yellow(num)}`);
s = s.replace(/:\s*(true|false|null)/g, (_, kw) => `: ${chalk.magenta(kw)}`);
return s;
}