redux-devtools/packages/redux-devtools-inspector-monitor/src/tabs/JSONDiff.tsx
Nathan Bierema b82de74592
Add ESM builds (#997)
* Use rollup for d3tooltip

* Use rollup for map2tree

* Set moduleResolution

* Use rollup for d3-state-visualizer

* Use rollup for react-base16-styling

* Use rollup for react-dock

* Use rollup for react-json-tree

* Use rollup for redux-devtools

* Use rollup for redux-devtools-intrument

* Use rollup for redux-devtools-chart-monitor

* Update export

* Use rollup for redux-devtools-dock-monitor

* Use rollup for redux-devtools-inspector-monitor

* Fix inspector demo

* Fix invalid eslint config

* Use rollup for inspector-monitor-test-tab

* Use rollup for inspector-monitor-trace-tab

* Use rollup for redux-devtools-log-monitor

* Use rollup for redux-devtools-remote

* Use rollup in redux-devtools-rtk-query-monitor

* Use rollup for redux-devtools-serialize

* Fix redux-devtools examples

* Use rollup for redux-devtools-slider-monitor

* Fix slider examples

* Use rollup for redux-devtools-ui

* Use rollup for redux-devtools-utils

* Use rollup for redux-devtools-extension

* Use rollup for redux-devtools-app

* Fix Webpack app build

* Fix extension build

* Turn on minimization

* Update CLI
2022-01-10 15:41:53 +00:00

171 lines
4.2 KiB
TypeScript

import React, { Component } from 'react';
import { JSONTree } from 'react-json-tree';
import { stringify } from 'javascript-stringify';
import { Delta } from 'jsondiffpatch';
import { StylingFunction } from 'react-base16-styling';
import { Base16Theme } from 'redux-devtools-themes';
import getItemString from './getItemString';
import getJsonTreeTheme from './getJsonTreeTheme';
function stringifyAndShrink(val: any, isWideLayout?: boolean) {
if (val === null) {
return 'null';
}
const str = stringify(val);
if (typeof str === 'undefined') {
return 'undefined';
}
if (isWideLayout)
return str.length > 42 ? str.substr(0, 30) + '…' + str.substr(-10) : str;
return str.length > 22 ? `${str.substr(0, 15)}${str.substr(-5)}` : str;
}
const expandFirstLevel = (
keyName: (string | number)[],
data: any,
level: number
) => level <= 1;
function prepareDelta(value: any) {
if (value && value._t === 'a') {
const res: { [key: string]: any } = {};
for (const key in value) {
if (key !== '_t') {
if (key[0] === '_' && !value[key.substr(1)]) {
res[key.substr(1)] = value[key];
} else if (value['_' + key]) {
res[key] = [value['_' + key][0], value[key][0]];
} else if (!value['_' + key] && key[0] !== '_') {
res[key] = value[key];
}
}
}
return res;
}
return value;
}
interface Props {
delta: Delta | null | undefined | false;
styling: StylingFunction;
base16Theme: Base16Theme;
invertTheme: boolean;
labelRenderer: (
keyPath: (string | number)[],
nodeType: string,
expanded: boolean,
expandable: boolean
) => React.ReactNode;
isWideLayout: boolean;
dataTypeKey: string | symbol | undefined;
}
interface State {
data: any;
}
export default class JSONDiff extends Component<Props, State> {
state: State = { data: {} };
componentDidMount() {
this.updateData();
}
componentDidUpdate(prevProps: Props) {
if (prevProps.delta !== this.props.delta) {
this.updateData();
}
}
updateData() {
// this magically fixes weird React error, where it can't find a node in tree
// if we set `delta` as JSONTree data right away
// https://github.com/alexkuz/redux-devtools-inspector/issues/17
this.setState({ data: this.props.delta });
}
render() {
const { styling, base16Theme, ...props } = this.props;
if (!this.state.data) {
return <div {...styling('stateDiffEmpty')}>(states are equal)</div>;
}
return (
<JSONTree
{...props}
theme={getJsonTreeTheme(base16Theme)}
data={this.state.data}
getItemString={this.getItemString}
valueRenderer={this.valueRenderer}
postprocessValue={prepareDelta}
isCustomNode={Array.isArray}
shouldExpandNode={expandFirstLevel}
hideRoot
/>
);
}
getItemString = (type: string, data: any) =>
getItemString(
this.props.styling,
type,
data,
this.props.dataTypeKey,
this.props.isWideLayout,
true
);
valueRenderer = (raw: any, value: any) => {
const { styling, isWideLayout } = this.props;
function renderSpan(name: string, body: string) {
return (
<span key={name} {...styling(['diff', name])}>
{body}
</span>
);
}
if (Array.isArray(value)) {
switch (value.length) {
case 1:
return (
<span {...styling('diffWrap')}>
{renderSpan(
'diffAdd',
stringifyAndShrink(value[0], isWideLayout)
)}
</span>
);
case 2:
return (
<span {...styling('diffWrap')}>
{renderSpan(
'diffUpdateFrom',
stringifyAndShrink(value[0], isWideLayout)
)}
{renderSpan('diffUpdateArrow', ' => ')}
{renderSpan(
'diffUpdateTo',
stringifyAndShrink(value[1], isWideLayout)
)}
</span>
);
case 3:
return (
<span {...styling('diffWrap')}>
{renderSpan('diffRemove', stringifyAndShrink(value[0]))}
</span>
);
}
}
return raw;
};
}