@tabula/ui-json-view
Version:
Allows to view JSON in interactive way
925 lines (871 loc) • 26.6 kB
JavaScript
// src/UiJsonView/UiJsonView.tsx
import { clsx as clsx8 } from "clsx/lite";
import { UiAnalytics } from "@tabula/ui-analytics";
// src/UiJsonView/UiJsonView.css.ts
var variants = { "static": "tabula_ui_json_view__10jrzlp1 tabula_ui_json_view__10jrzlp0", interactive: "tabula_ui_json_view__10jrzlp2 tabula_ui_json_view__10jrzlp0" };
// src/OptionsProvider.tsx
import { createContext, useContext, useMemo } from "react";
import { jsx } from "react/jsx-runtime";
var noop = () => {
};
var defaultValue = {
actions: {},
isCopyPathAllowed: true,
isCopyValueAllowed: true,
isInteractive: false,
showDataTypes: false,
showObjectSize: false,
onAction: noop,
onToggle: noop
};
var Context = createContext(defaultValue);
var OptionsProvider = ({
actions = defaultValue.actions,
children,
isCopyPathAllowed = defaultValue.isCopyPathAllowed,
isCopyValueAllowed = defaultValue.isCopyValueAllowed,
isInteractive = defaultValue.isInteractive,
onAction = defaultValue.onAction,
onToggle = defaultValue.onToggle,
onToggleDataTypes,
onToggleObjectSize,
shortStringAfterLength,
showDataTypes = defaultValue.showDataTypes,
showObjectSize = defaultValue.showObjectSize
}) => {
const value = useMemo(
() => ({
actions,
isCopyPathAllowed,
isCopyValueAllowed,
isInteractive,
onAction,
onToggle,
onToggleDataTypes,
onToggleObjectSize,
shortStringAfterLength,
showDataTypes,
showObjectSize
}),
[
actions,
isCopyPathAllowed,
isCopyValueAllowed,
isInteractive,
onAction,
onToggle,
onToggleDataTypes,
onToggleObjectSize,
shortStringAfterLength,
showDataTypes,
showObjectSize
]
);
return /* @__PURE__ */ jsx(Context.Provider, { value, children });
};
function useOptions() {
return useContext(Context);
}
// src/StaticView/StaticView.tsx
import { clsx as clsx6 } from "clsx/lite";
// src/StaticView/StaticView.css.ts
var options = "tabula_ui_json_view__1jk7hr11";
var root = "tabula_ui_json_view__1jk7hr10";
// src/Line/Line.tsx
import { memo as memo3 } from "react";
import { assignInlineVars } from "@vanilla-extract/dynamic";
import { clsx as clsx4 } from "clsx/lite";
// src/Line/Line.css.ts
var controls = { toggle: "tabula_ui_json_view__1oseowyb", action: "tabula_ui_json_view__1oseowyc" };
var level = "var(--tabula_ui_json_view__1oseowy0)";
var position = { isFirst: "tabula_ui_json_view__1oseowy1", isLast: "tabula_ui_json_view__1oseowy2" };
var variants2 = { bool: "tabula_ui_json_view__1oseowy4 tabula_ui_json_view__1oseowy3", null: "tabula_ui_json_view__1oseowy5 tabula_ui_json_view__1oseowy3", "int": "tabula_ui_json_view__1oseowy6 tabula_ui_json_view__1oseowy3", "float": "tabula_ui_json_view__1oseowy7 tabula_ui_json_view__1oseowy3", string: "tabula_ui_json_view__1oseowy8 tabula_ui_json_view__1oseowy3", boundary: "tabula_ui_json_view__1oseowy9 tabula_ui_json_view__1oseowy3", placeholder: "tabula_ui_json_view__1oseowya tabula_ui_json_view__1oseowy3" };
// src/Action/Action.tsx
import { clsx } from "clsx/lite";
import { useUiTrackId } from "@tabula/ui-analytics";
// src/Action/Action.css.ts
var root2 = "tabula_ui_json_view__befjea0";
// src/Action/Action.tsx
import { jsx as jsx2 } from "react/jsx-runtime";
var Action = ({ action, className, children, jsonPath, trackId }) => {
const { onAction } = useOptions();
const actualTrackId = useUiTrackId(trackId ?? false);
const handleClick = () => {
onAction(jsonPath, action);
};
return /* @__PURE__ */ jsx2(
"button",
{
className: clsx(root2, className),
"data-track-id": actualTrackId,
onClick: handleClick,
type: "button",
children
}
);
};
// src/Copy/Copy.tsx
import { useRef, useState } from "react";
import { clsx as clsx2 } from "clsx/lite";
// src/Copy/Copy.css.ts
var copied = "tabula_ui_json_view__570zx20";
// src/Copy/Copy.tsx
import { jsx as jsx3 } from "react/jsx-runtime";
var delay = 1e3;
var Copy = ({
className,
defaultLabel,
jsonPath,
successLabel,
toClipboard,
trackId
}) => {
const [isCopied, setIsCopied] = useState(false);
const timerRef = useRef(null);
const action = (_, query) => {
navigator.clipboard.writeText(toClipboard(jsonPath, query)).then(() => {
setIsCopied(true);
if (timerRef.current != null) {
window.clearTimeout(timerRef.current);
}
timerRef.current = window.setTimeout(() => {
setIsCopied(false);
}, delay);
}).catch(() => {
setIsCopied(false);
});
};
return /* @__PURE__ */ jsx3(
Action,
{
className: clsx2(className, isCopied && copied),
action,
jsonPath,
trackId,
children: isCopied ? successLabel : defaultLabel
}
);
};
// src/Actions.tsx
import { jsx as jsx4 } from "react/jsx-runtime";
function jsonPathToClipboard(jsonPath) {
return jsonPath;
}
function valueToClipboard(jsonPath, query) {
const value = query(jsonPath);
return JSON.stringify(value, null, 4);
}
var Actions = ({ className, jsonPath, type }) => {
const { actions, isCopyPathAllowed, isCopyValueAllowed, isInteractive } = useOptions();
if (!isInteractive) {
return null;
}
const body = [];
if (isCopyValueAllowed) {
body.push(
/* @__PURE__ */ jsx4(
Copy,
{
className,
defaultLabel: "Copy",
jsonPath,
successLabel: "Copied!",
toClipboard: valueToClipboard,
trackId: "copy-json"
},
"copy-value"
)
);
}
if (isCopyPathAllowed) {
body.push(
/* @__PURE__ */ jsx4(
Copy,
{
className,
defaultLabel: "Copy JSONPath",
jsonPath,
successLabel: "Copied!",
toClipboard: jsonPathToClipboard,
trackId: "copy-json-path"
},
"copy-path"
)
);
}
for (const [name, action] of Object.entries(actions)) {
if (typeof action === "function") {
body.push(
/* @__PURE__ */ jsx4(Action, { className, action, jsonPath, children: name }, name)
);
continue;
}
const { action: actionFn, isVisible, trackId } = action;
if (isVisible != null && !isVisible(jsonPath, type)) {
continue;
}
body.push(
/* @__PURE__ */ jsx4(
Action,
{
className,
action: actionFn,
jsonPath,
trackId,
children: name
},
name
)
);
}
return body;
};
// src/Property/Property.css.ts
var root3 = "tabula_ui_json_view__1vkacjt0";
// src/Property/Property.tsx
import { jsxs } from "react/jsx-runtime";
var Property = ({ property }) => {
if (property == null) {
return null;
}
const name = typeof property === "number" ? property : JSON.stringify(property);
return /* @__PURE__ */ jsxs("span", { className: root3, children: [
name,
"\xA0:\xA0"
] });
};
// src/Rest/Rest.css.ts
var root4 = "tabula_ui_json_view__1g4h8a90";
// src/Rest/Rest.tsx
import { jsx as jsx5 } from "react/jsx-runtime";
var Rest = ({ path }) => {
const { onToggle } = useOptions();
const handleClick = () => {
onToggle(path);
};
return (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events
/* @__PURE__ */ jsx5("span", { className: root4, onClick: handleClick, role: "button", tabIndex: -1, children: "..." })
);
};
// src/Size/Size.css.ts
var root5 = "tabula_ui_json_view__1fpwoua0";
// src/Size/Size.tsx
import { jsxs as jsxs2 } from "react/jsx-runtime";
var Size = ({ size }) => {
const { showObjectSize } = useOptions();
if (!showObjectSize) {
return null;
}
return /* @__PURE__ */ jsxs2("span", { className: root5, children: [
"\xA0",
size === 1 ? "1 item" : `${size} items`
] });
};
// src/StringValue/StringValue.css.ts
var root6 = "tabula_ui_json_view__3x419u0";
// src/StringValue/StringValue.hooks.ts
import { useCallback, useEffect, useState as useState2 } from "react";
function useStringCollapse(children, limit) {
const initialState = limit != null && children.length > limit;
const [isCollapsed, setIsCollapsed] = useState2(initialState);
useEffect(() => {
setIsCollapsed(initialState);
}, [initialState]);
const onToggle = useCallback(() => {
setIsCollapsed((value) => !value);
}, []);
return [limit != null && children.length > limit, isCollapsed, onToggle];
}
// src/StringValue/StringValue.tsx
import { jsx as jsx6 } from "react/jsx-runtime";
var StringValue = ({ children }) => {
const { shortStringAfterLength } = useOptions();
const [isCollapsible, isCollapsed, onToggle] = useStringCollapse(
children,
shortStringAfterLength
);
if (!isCollapsible) {
return children;
}
return (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events
/* @__PURE__ */ jsx6("span", { className: root6, onClick: onToggle, role: "button", tabIndex: -1, children: isCollapsed ? `${children.slice(0, shortStringAfterLength)}...` : children })
);
};
// src/Toggle/Toggle.tsx
import { clsx as clsx3 } from "clsx/lite";
// src/Toggle/assets/collapse.svg?svgr
import * as React from "react";
import { memo } from "react";
import { jsx as jsx7 } from "react/jsx-runtime";
var CollapseIcon = (props) => /* @__PURE__ */ jsx7("svg", { width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx7("path", { stroke: "currentColor", d: "M4 8h8" }) });
var Memo = memo(CollapseIcon);
if (import.meta.env.DEV) {
Memo.displayName = "CollapseIcon";
}
// src/Toggle/assets/expand.svg?svgr
import * as React2 from "react";
import { memo as memo2 } from "react";
import { jsx as jsx8 } from "react/jsx-runtime";
var ExpandIcon = (props) => /* @__PURE__ */ jsx8("svg", { width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx8("path", { stroke: "currentColor", d: "M4 8h8M8 4v8" }) });
var Memo2 = memo2(ExpandIcon);
if (import.meta.env.DEV) {
Memo2.displayName = "ExpandIcon";
}
// src/Toggle/Toggle.css.ts
var root7 = "tabula_ui_json_view__2gtjvm0";
// src/Toggle/Toggle.tsx
import { jsx as jsx9 } from "react/jsx-runtime";
var Toggle = ({ className, isCollapsed, path }) => {
const { isInteractive, onToggle } = useOptions();
if (!isInteractive) {
return null;
}
const handleClick = () => {
onToggle(path);
};
return /* @__PURE__ */ jsx9("button", { className: clsx3(root7, className), onClick: handleClick, type: "button", children: isCollapsed ? /* @__PURE__ */ jsx9(Memo2, {}) : /* @__PURE__ */ jsx9(Memo, {}) });
};
// src/Type/Type.css.ts
var root8 = "tabula_ui_json_view__r98z5d0";
// src/Type/Type.tsx
import { jsxs as jsxs3 } from "react/jsx-runtime";
var Type = ({ type }) => {
const { showDataTypes } = useOptions();
if (!showDataTypes || type === "null") {
return null;
}
return /* @__PURE__ */ jsxs3("span", { className: root8, children: [
type,
"\xA0"
] });
};
// src/Line/Line.tsx
import { Fragment, jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
var Line = memo3(function Line2({ line, style }) {
const positionClassName = clsx4(line.isFirst && position.isFirst, line.isLast && position.isLast);
const rootStyle = { ...style, ...assignInlineVars({ [level]: `${line.level}` }) };
switch (line.kind) {
case 0 /* Value */: {
const { jsonPath, property, type, value } = line;
return /* @__PURE__ */ jsxs4("div", { className: clsx4(variants2[type], positionClassName), style: rootStyle, children: [
/* @__PURE__ */ jsx10(Property, { property }),
/* @__PURE__ */ jsx10(Type, { type }),
type === "string" ? /* @__PURE__ */ jsx10(StringValue, { children: value }) : value,
/* @__PURE__ */ jsx10(Actions, { className: controls.action, jsonPath, type })
] });
}
case 1 /* Open */: {
const { closeSymbol, isCollapsed, jsonPath, openSymbol, path, property, size, type } = line;
return /* @__PURE__ */ jsxs4("div", { className: clsx4(variants2.boundary, positionClassName), style: rootStyle, children: [
/* @__PURE__ */ jsx10(Toggle, { className: controls.toggle, isCollapsed, path }),
/* @__PURE__ */ jsx10(Property, { property }),
isCollapsed ? /* @__PURE__ */ jsxs4(Fragment, { children: [
openSymbol,
/* @__PURE__ */ jsx10(Rest, { path }),
closeSymbol
] }) : openSymbol,
/* @__PURE__ */ jsx10(Size, { size }),
/* @__PURE__ */ jsx10(Actions, { className: controls.action, jsonPath, type })
] });
}
case 2 /* Close */: {
const { closeSymbol } = line;
return /* @__PURE__ */ jsx10("div", { className: clsx4(variants2.boundary, positionClassName), style: rootStyle, children: closeSymbol });
}
case 3 /* Placeholder */: {
const { placeholder } = line;
return /* @__PURE__ */ jsx10("div", { className: clsx4(variants2.placeholder, positionClassName), style: rootStyle, children: placeholder });
}
}
});
// src/Options/Options.tsx
import { clsx as clsx5 } from "clsx/lite";
// src/Options/Options.css.ts
var root9 = "tabula_ui_json_view__ke04bl0";
// src/Option/Option.css.ts
var handle = "tabula_ui_json_view__1remqm63";
var indicator = "tabula_ui_json_view__1remqm62";
var input = "tabula_ui_json_view__1remqm61";
var root10 = "tabula_ui_json_view__1remqm60";
// src/Option/Option.tsx
import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
var Option = ({ children, onChange, value }) => {
const handleChange = ({ currentTarget }) => {
onChange(currentTarget.checked);
};
return /* @__PURE__ */ jsxs5("label", { className: root10, children: [
/* @__PURE__ */ jsx11("input", { checked: value, className: input, onChange: handleChange, type: "checkbox" }),
/* @__PURE__ */ jsx11("div", { className: indicator, children: /* @__PURE__ */ jsx11("div", { className: handle }) }),
children
] });
};
// src/Options/Options.tsx
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
var Options = ({ className }) => {
const { onToggleDataTypes, onToggleObjectSize, showDataTypes, showObjectSize } = useOptions();
if (onToggleDataTypes == null && onToggleObjectSize == null) {
return null;
}
return /* @__PURE__ */ jsxs6("div", { className: clsx5(root9, className), children: [
onToggleDataTypes && /* @__PURE__ */ jsx12(Option, { onChange: onToggleDataTypes, value: showDataTypes, children: "Show types" }),
onToggleObjectSize && /* @__PURE__ */ jsx12(Option, { onChange: onToggleObjectSize, value: showObjectSize, children: "Show sizes" })
] });
};
// src/StaticView/StaticView.tsx
import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
var StaticView = ({ className, lines }) => {
const children = lines.map((line) => /* @__PURE__ */ jsx13(Line, { line }, line.path));
return /* @__PURE__ */ jsxs7("div", { className: clsx6(className, root), children: [
/* @__PURE__ */ jsx13(Options, { className: options }),
children
] });
};
// src/VirtualView/VirtualView.tsx
import { useCallback as useCallback2 } from "react";
import { clsx as clsx7 } from "clsx/lite";
import { VariableSizeList } from "react-window";
import { useSize } from "@tabula/use-size";
// src/shared.css.ts
var basePadding = 16;
var itemHeight = 24;
// src/VirtualView/VirtualView.css.ts
var list = "tabula_ui_json_view__nub1zk1";
var options2 = "tabula_ui_json_view__nub1zk2";
var root11 = "tabula_ui_json_view__nub1zk0";
// src/VirtualView/VirtualView.tsx
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
function itemKey(index, lines) {
return lines[index].path;
}
var lineRenderer = ({
index,
data,
style
}) => {
const line = data[index];
return /* @__PURE__ */ jsx14(Line, { line, style });
};
var VirtualView = ({ className, lines }) => {
const [ref, { height }] = useSize();
const itemSize = useCallback2(
(index) => {
const { isFirst, isLast } = lines[index];
let size = itemHeight;
if (isFirst) {
size += basePadding;
}
if (isLast) {
size += basePadding;
}
return size;
},
[lines]
);
return /* @__PURE__ */ jsxs8("div", { className: clsx7(className, root11), ref, children: [
/* @__PURE__ */ jsx14(
VariableSizeList,
{
className: list,
height,
itemCount: lines.length,
itemData: lines,
itemKey,
itemSize,
overscanCount: Math.floor(height / itemHeight / 4),
width: "100%",
children: lineRenderer
}
),
/* @__PURE__ */ jsx14(Options, { className: options2 })
] });
};
// src/UiJsonView/hooks/useActionHandler.ts
import { useMemo as useMemo2 } from "react";
import jp from "jsonpath";
function useActionHandler(value, isValid) {
return useMemo2(() => {
if (!isValid) {
return () => null;
}
const query = (jsonPath) => jp.value(value, jsonPath);
return (jsonPath, action) => {
action(jsonPath, query);
};
}, [value, isValid]);
}
// src/UiJsonView/hooks/useCollapsedKeys.ts
import { useCallback as useCallback3, useEffect as useEffect2, useState as useState3 } from "react";
var Registry = class _Registry {
constructor(keys = /* @__PURE__ */ new Set()) {
this.keys = keys;
}
get isEmpty() {
return this.keys.size === 0;
}
has(key) {
return this.keys.has(key);
}
toggle(key) {
if (this.keys.has(key)) {
this.keys.delete(key);
} else {
this.keys.add(key);
}
return new _Registry(this.keys);
}
};
function initCollapsedKeys(lines, collapsed) {
const keys = /* @__PURE__ */ new Set();
if (collapsed !== false) {
const minLevel = collapsed === true ? 0 : collapsed;
for (const line of lines) {
if (line.kind === 1 /* Open */ && line.level >= minLevel) {
keys.add(line.path);
}
}
}
return new Registry(keys);
}
function useCollapsedKeys(lines, collapsed = false) {
const [keys, setKeys] = useState3(() => initCollapsedKeys(lines, collapsed));
useEffect2(() => {
setKeys(initCollapsedKeys(lines, collapsed));
}, [lines, collapsed]);
const onToggle = useCallback3((key) => {
setKeys((current) => current.toggle(key));
}, []);
return [keys, onToggle];
}
// src/UiJsonView/hooks/useCollapsedLines.ts
import { useMemo as useMemo3 } from "react";
function markPositions(lines) {
if (lines.length === 0) {
return;
}
lines[0] = { ...lines[0], isFirst: true };
const lastIndex = lines.length - 1;
lines[lastIndex] = { ...lines[lastIndex], isLast: true };
}
function useCollapsedLines(allLines, collapsedKeys) {
return useMemo3(() => {
if (collapsedKeys.isEmpty) {
const lines2 = [...allLines];
markPositions(lines2);
return lines2;
}
const lines = [];
let skip = null;
for (const line of allLines) {
if (skip != null) {
if (line.path.startsWith(skip)) {
continue;
} else {
skip = null;
}
}
if (line.kind === 1 /* Open */ && collapsedKeys.has(line.path)) {
skip = `${line.path}.`;
lines.push({ ...line, isCollapsed: true });
} else {
lines.push(line);
}
}
markPositions(lines);
return lines;
}, [allLines, collapsedKeys]);
}
// src/UiJsonView/hooks/useLines/useLines.ts
import { useMemo as useMemo4 } from "react";
// src/UiJsonView/hooks/useLines/isPrimitiveValue.ts
function isPrimitiveValue(value) {
if (value == null) {
return true;
}
const type = typeof value;
return type === "boolean" || type === "number" || type === "string";
}
// src/UiJsonView/hooks/useLines/itemFrom.ts
import jp2 from "jsonpath";
function typedValueOf(value) {
if (value == null) {
return ["null", "null"];
}
switch (typeof value) {
case "boolean": {
return ["bool", value.toString()];
}
case "number": {
return [Number.isInteger(value) ? "int" : "float", value.toString()];
}
default: {
return ["string", JSON.stringify(value)];
}
}
}
function valueLineItemFrom(source, { jsonPath: jsonPathComponents, level: level2, path, property }) {
const jsonPath = jp2.stringify(jsonPathComponents);
const [type, value] = typedValueOf(source);
const line = { kind: 0 /* Value */, jsonPath, path, level: level2, type, value };
if (property != null) {
line.property = property;
}
return { isLine: true, line };
}
function openItemFrom({
closeSymbol,
jsonPath,
level: level2,
openSymbol,
path,
property,
size,
type
}) {
const line = {
kind: 1 /* Open */,
jsonPath: jp2.stringify(jsonPath),
level: level2,
path,
openSymbol,
closeSymbol,
size,
type
};
if (property != null) {
line.property = property;
}
return { isLine: true, line };
}
function closeItemFrom({ closeSymbol, level: level2, path, size }) {
return {
isLine: true,
line: {
kind: 2 /* Close */,
level: level2,
// NOTE: If size is 0, then an empty placeholder will be added, and size will be 1.
path: `${path}.${Math.max(size, 1)}`,
closeSymbol
}
};
}
function emptyItemFrom({ level: level2, path }) {
return {
isLine: true,
line: {
kind: 3 /* Placeholder */,
level: level2 + 1,
path: `${path}.0`,
placeholder: "empty"
}
};
}
function valueItemFrom({
index,
jsonPath,
level: level2,
path,
property,
value
}) {
return {
isLine: false,
jsonPath: [...jsonPath, property],
level: level2 + 1,
path: `${path}.${index}`,
property,
value
};
}
// src/UiJsonView/hooks/useLines/metaOf.ts
function arrayChildrenOf(value) {
return value.map((child, index) => [index, index, child]);
}
function objectChildrenOf(value) {
return Object.entries(value).map(([property, child], index) => [index, property, child]);
}
function metaOf(value) {
if (Array.isArray(value)) {
const children2 = arrayChildrenOf(value);
return {
children: children2,
openSymbol: "[",
closeSymbol: "]",
size: children2.length,
type: "array"
};
}
const children = objectChildrenOf(value);
return {
children,
openSymbol: "{",
closeSymbol: "}",
size: children.length,
type: "object"
};
}
// src/UiJsonView/hooks/useLines/enqueueItemsFrom.ts
function enqueueItemsFrom(parent) {
const { jsonPath, level: level2, path, property, value: source, next } = parent;
if (isPrimitiveValue(source)) {
const item = valueLineItemFrom(source, {
jsonPath,
path,
level: level2,
property
});
item.next = next;
parent.next = item;
return;
}
const { children, openSymbol, closeSymbol, size, type } = metaOf(source);
const open = openItemFrom({
jsonPath,
level: level2,
path,
property,
openSymbol,
closeSymbol,
size,
type
});
const close = closeItemFrom({
level: level2,
path,
closeSymbol,
size
});
close.next = next;
parent.next = open;
let cursor = open;
if (size === 0) {
const empty = emptyItemFrom({ path, level: level2 });
empty.next = close;
cursor.next = empty;
} else {
for (const [index, childProperty, value] of children) {
const item = valueItemFrom({
jsonPath,
level: level2,
path,
index,
property: childProperty,
value
});
cursor.next = item;
cursor = item;
}
cursor.next = close;
}
}
// src/UiJsonView/hooks/useLines/useLines.ts
function useLines(value, isValid, maxNumberOfLines) {
return useMemo4(() => {
if (!isValid) {
return [
{
level: 0,
path: "0",
placeholder: "Invalid JSON",
kind: 3 /* Placeholder */
}
];
}
let cursor = {
isLine: false,
jsonPath: ["$"],
level: 0,
path: "0",
value
};
const lines = [];
while (cursor != null) {
if (cursor.isLine) {
lines.push(cursor.line);
} else {
enqueueItemsFrom(cursor);
}
if (lines.length === maxNumberOfLines) {
lines.push({
kind: 3 /* Placeholder */,
level: 0,
path: `more`,
placeholder: "..."
});
break;
}
cursor = cursor.next;
}
return lines;
}, [value, isValid, maxNumberOfLines]);
}
// src/UiJsonView/hooks/useValue.ts
import { useMemo as useMemo5 } from "react";
function useValue(source) {
return useMemo5(() => {
try {
const value = JSON.parse(source);
return [value, true];
} catch {
return [null, false];
}
}, [source]);
}
// src/UiJsonView/UiJsonView.tsx
import { jsx as jsx15 } from "react/jsx-runtime";
var UiJsonView = ({
actions,
className = "",
collapsed,
isCopyPathAllowed,
isCopyValueAllowed,
isInteractive,
isVirtual,
limit,
onToggleDataTypes,
onToggleObjectSize,
shortStringAfterLength,
showDataTypes,
showObjectSize,
source,
trackId
}) => {
const [allowInteractions, maxNumberOfLines] = limit != null && limit > 0 ? [false, limit] : [isInteractive, Number.POSITIVE_INFINITY];
const [value, isValid] = useValue(source);
const allLines = useLines(value, isValid, maxNumberOfLines);
const [collapsedKeys, onToggle] = useCollapsedKeys(
allLines,
allowInteractions ? collapsed : false
);
const lines = useCollapsedLines(allLines, collapsedKeys);
const containerClassName = lines.length === 0 || lines[0].kind !== 1 /* Open */ || !allowInteractions ? variants.static : variants.interactive;
const onAction = useActionHandler(value, isValid);
const View = isVirtual ? VirtualView : StaticView;
return /* @__PURE__ */ jsx15(UiAnalytics, { trackId, children: /* @__PURE__ */ jsx15(
OptionsProvider,
{
actions,
isCopyPathAllowed,
isCopyValueAllowed,
isInteractive: allowInteractions,
onAction,
onToggle,
onToggleDataTypes,
onToggleObjectSize,
shortStringAfterLength,
showDataTypes,
showObjectSize,
children: /* @__PURE__ */ jsx15(View, { className: clsx8(containerClassName, className), lines })
}
) });
};
if (import.meta.env.DEV) {
UiJsonView.displayName = "ui-json-view(UiJsonView)";
}
export {
UiJsonView
};
// post-build: auto import bundled styles
import "./index.css";
//# sourceMappingURL=index.js.map