mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-24 15:09:49 +03:00
stash
This commit is contained in:
parent
35fc6ec837
commit
b2de052522
|
@ -142,7 +142,7 @@ const mergeStylings = (
|
||||||
|
|
||||||
const getStylingByKeys = (
|
const getStylingByKeys = (
|
||||||
mergedStyling: StylingConfig,
|
mergedStyling: StylingConfig,
|
||||||
keys: (string | false) | (string | false)[],
|
keys: (string | false | undefined) | (string | false | undefined)[],
|
||||||
...args: any[]
|
...args: any[]
|
||||||
): Styling => {
|
): Styling => {
|
||||||
if (keys === null) {
|
if (keys === null) {
|
||||||
|
|
|
@ -27,6 +27,6 @@ export type StylingConfig = {
|
||||||
export type Theme = string | Base16Theme | StylingConfig;
|
export type Theme = string | Base16Theme | StylingConfig;
|
||||||
|
|
||||||
export type StylingFunction = (
|
export type StylingFunction = (
|
||||||
keys: (string | false) | (string | false)[],
|
keys: (string | false | undefined) | (string | false | undefined)[],
|
||||||
...rest: any[]
|
...rest: any[]
|
||||||
) => Styling;
|
) => Styling;
|
||||||
|
|
|
@ -5,7 +5,6 @@ const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: isProduction ? 'production' : 'development',
|
mode: isProduction ? 'production' : 'development',
|
||||||
devtool: 'eval',
|
|
||||||
entry: isProduction
|
entry: isProduction
|
||||||
? ['./demo/src/index']
|
? ['./demo/src/index']
|
||||||
: [
|
: [
|
||||||
|
@ -18,10 +17,6 @@ module.exports = {
|
||||||
filename: 'bundle.js',
|
filename: 'bundle.js',
|
||||||
publicPath: isProduction ? 'static/' : '/static/',
|
publicPath: isProduction ? 'static/' : '/static/',
|
||||||
},
|
},
|
||||||
plugins: isProduction ? [] : [new webpack.HotModuleReplacementPlugin()],
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
||||||
},
|
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
@ -34,6 +29,10 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||||
|
},
|
||||||
|
plugins: isProduction ? [] : [new webpack.HotModuleReplacementPlugin()],
|
||||||
devServer: isProduction
|
devServer: isProduction
|
||||||
? null
|
? null
|
||||||
: {
|
: {
|
||||||
|
@ -46,4 +45,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
historyApiFallback: true,
|
historyApiFallback: true,
|
||||||
},
|
},
|
||||||
|
devtool: 'eval-source-map',
|
||||||
};
|
};
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/dateformat": "^3.0.1",
|
"@types/dateformat": "^3.0.1",
|
||||||
|
"@types/hex-rgba": "^1.0.0",
|
||||||
"@types/lodash.debounce": "^4.0.6",
|
"@types/lodash.debounce": "^4.0.6",
|
||||||
"@types/react": "^16.9.46",
|
"@types/react": "^16.9.46",
|
||||||
"@types/react-dragula": "^1.1.0",
|
"@types/react-dragula": "^1.1.0",
|
||||||
|
|
|
@ -164,18 +164,20 @@ export default class ActionList<
|
||||||
isSelected={
|
isSelected={
|
||||||
(startActionId !== null &&
|
(startActionId !== null &&
|
||||||
actionId >= startActionId &&
|
actionId >= startActionId &&
|
||||||
actionId <= selectedActionId) ||
|
actionId <= (selectedActionId as number)) ||
|
||||||
actionId === selectedActionId
|
actionId === selectedActionId
|
||||||
}
|
}
|
||||||
isInFuture={
|
isInFuture={
|
||||||
actionIds.indexOf(actionId) > actionIds.indexOf(currentActionId)
|
actionIds.indexOf(actionId) > actionIds.indexOf(currentActionId)
|
||||||
}
|
}
|
||||||
onSelect={(e) => onSelect(e, actionId)}
|
onSelect={(e: React.MouseEvent<HTMLDivElement>) =>
|
||||||
|
onSelect(e, actionId)
|
||||||
|
}
|
||||||
timestamps={getTimestamps(actions, actionIds, actionId)}
|
timestamps={getTimestamps(actions, actionIds, actionId)}
|
||||||
action={actions[actionId].action}
|
action={actions[actionId].action}
|
||||||
onToggleClick={() => onToggleAction(actionId)}
|
onToggleClick={() => onToggleAction(actionId)}
|
||||||
onJumpClick={() => onJumpToState(actionId)}
|
onJumpClick={() => onJumpToState(actionId)}
|
||||||
onCommitClick={() => onCommit(actionId)}
|
onCommitClick={() => onCommit()}
|
||||||
hideActionButtons={hideActionButtons}
|
hideActionButtons={hideActionButtons}
|
||||||
isSkipped={skippedActionIds.indexOf(actionId) !== -1}
|
isSkipped={skippedActionIds.indexOf(actionId) !== -1}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,10 +1,24 @@
|
||||||
import React from 'react';
|
import React, { FunctionComponent } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { StylingFunction } from 'react-base16-styling';
|
||||||
import RightSlider from './RightSlider';
|
import RightSlider from './RightSlider';
|
||||||
|
|
||||||
const getActiveButtons = (hasSkippedActions) =>
|
const getActiveButtons = (hasSkippedActions: boolean): ('Sweep' | 'Commit')[] =>
|
||||||
[hasSkippedActions && 'Sweep', 'Commit'].filter((a) => a);
|
[hasSkippedActions && 'Sweep', 'Commit'].filter(
|
||||||
|
(a): a is 'Sweep' | 'Commit' => !!a
|
||||||
|
);
|
||||||
|
|
||||||
const ActionListHeader = ({
|
interface Props {
|
||||||
|
styling: StylingFunction;
|
||||||
|
onSearch: (value: string) => void;
|
||||||
|
onCommit: () => void;
|
||||||
|
onSweep: () => void;
|
||||||
|
hideMainButtons: boolean | undefined;
|
||||||
|
hasSkippedActions: boolean;
|
||||||
|
hasStagedActions: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ActionListHeader: FunctionComponent<Props> = ({
|
||||||
styling,
|
styling,
|
||||||
onSearch,
|
onSearch,
|
||||||
hasSkippedActions,
|
hasSkippedActions,
|
||||||
|
@ -48,4 +62,14 @@ const ActionListHeader = ({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ActionListHeader.propTypes = {
|
||||||
|
styling: PropTypes.func.isRequired,
|
||||||
|
onSearch: PropTypes.func.isRequired,
|
||||||
|
onCommit: PropTypes.func.isRequired,
|
||||||
|
onSweep: PropTypes.func.isRequired,
|
||||||
|
hideMainButtons: PropTypes.bool,
|
||||||
|
hasSkippedActions: PropTypes.bool.isRequired,
|
||||||
|
hasStagedActions: PropTypes.bool.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default ActionListHeader;
|
export default ActionListHeader;
|
||||||
|
|
|
@ -1,10 +1,43 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { DEFAULT_STATE } from './redux';
|
import { Base16Theme } from 'redux-devtools-themes';
|
||||||
|
import { Action } from 'redux';
|
||||||
|
import { StylingFunction } from 'react-base16-styling';
|
||||||
|
import { PerformAction } from 'redux-devtools';
|
||||||
|
import { Delta } from 'jsondiffpatch';
|
||||||
|
import { DEFAULT_STATE, DevtoolsInspectorState } from './redux';
|
||||||
import ActionPreviewHeader from './ActionPreviewHeader';
|
import ActionPreviewHeader from './ActionPreviewHeader';
|
||||||
import DiffTab from './tabs/DiffTab';
|
import DiffTab from './tabs/DiffTab';
|
||||||
import StateTab from './tabs/StateTab';
|
import StateTab from './tabs/StateTab';
|
||||||
import ActionTab from './tabs/ActionTab';
|
import ActionTab from './tabs/ActionTab';
|
||||||
|
|
||||||
|
export interface TabComponentProps<S, A extends Action<unknown>> {
|
||||||
|
labelRenderer: (
|
||||||
|
keyPath: (string | number)[],
|
||||||
|
nodeType: string,
|
||||||
|
expanded: boolean,
|
||||||
|
expandable: boolean
|
||||||
|
) => React.ReactNode;
|
||||||
|
styling: StylingFunction;
|
||||||
|
computedStates: { state: S; error?: string }[];
|
||||||
|
actions: { [actionId: number]: PerformAction<A> };
|
||||||
|
selectedActionId: number | null;
|
||||||
|
startActionId: number | null;
|
||||||
|
base16Theme: Base16Theme;
|
||||||
|
invertTheme: boolean;
|
||||||
|
isWideLayout: boolean;
|
||||||
|
dataTypeKey: string | undefined;
|
||||||
|
delta: Delta | null | undefined | false;
|
||||||
|
action: A;
|
||||||
|
nextState: S;
|
||||||
|
monitorState: DevtoolsInspectorState;
|
||||||
|
updateMonitorState: (monitorState: Partial<DevtoolsInspectorState>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Tab<S, A extends Action<unknown>> {
|
||||||
|
name: string;
|
||||||
|
component: React.ComponentType<TabComponentProps<S, A>>;
|
||||||
|
}
|
||||||
|
|
||||||
const DEFAULT_TABS = [
|
const DEFAULT_TABS = [
|
||||||
{
|
{
|
||||||
name: 'Action',
|
name: 'Action',
|
||||||
|
@ -20,7 +53,32 @@ const DEFAULT_TABS = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
class ActionPreview extends Component {
|
interface Props<S, A extends Action<unknown>> {
|
||||||
|
base16Theme: Base16Theme;
|
||||||
|
invertTheme: boolean;
|
||||||
|
isWideLayout: boolean;
|
||||||
|
tabs: Tab<S, A>[] | ((tabs: Tab<S, A>[]) => Tab<S, A>[]);
|
||||||
|
tabName: string;
|
||||||
|
delta: Delta | null | undefined | false;
|
||||||
|
error: string | undefined;
|
||||||
|
nextState: S;
|
||||||
|
computedStates: { state: S; error?: string }[];
|
||||||
|
action: A;
|
||||||
|
actions: { [actionId: number]: PerformAction<A> };
|
||||||
|
selectedActionId: number | null;
|
||||||
|
startActionId: number | null;
|
||||||
|
dataTypeKey: string | undefined;
|
||||||
|
monitorState: DevtoolsInspectorState;
|
||||||
|
updateMonitorState: (monitorState: Partial<DevtoolsInspectorState>) => void;
|
||||||
|
styling: StylingFunction;
|
||||||
|
onInspectPath: (path: (string | number)[]) => void;
|
||||||
|
inspectedPath: (string | number)[];
|
||||||
|
onSelectTab: (tabName: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActionPreview<S, A extends Action<unknown>> extends Component<
|
||||||
|
Props<S, A>
|
||||||
|
> {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
tabName: DEFAULT_STATE.tabName,
|
tabName: DEFAULT_STATE.tabName,
|
||||||
};
|
};
|
||||||
|
@ -49,21 +107,21 @@ class ActionPreview extends Component {
|
||||||
updateMonitorState,
|
updateMonitorState,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const renderedTabs =
|
const renderedTabs: Tab<S, A>[] =
|
||||||
typeof tabs === 'function'
|
typeof tabs === 'function'
|
||||||
? tabs(DEFAULT_TABS)
|
? tabs(DEFAULT_TABS as Tab<S, A>[])
|
||||||
: tabs
|
: tabs
|
||||||
? tabs
|
? tabs
|
||||||
: DEFAULT_TABS;
|
: (DEFAULT_TABS as Tab<S, A>[]);
|
||||||
|
|
||||||
const { component: TabComponent } =
|
const { component: TabComponent } =
|
||||||
renderedTabs.find((tab) => tab.name === tabName) ||
|
renderedTabs.find((tab) => tab.name === tabName) ||
|
||||||
renderedTabs.find((tab) => tab.name === DEFAULT_STATE.tabName);
|
renderedTabs.find((tab) => tab.name === DEFAULT_STATE.tabName)!;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key="actionPreview" {...styling('actionPreview')}>
|
<div key="actionPreview" {...styling('actionPreview')}>
|
||||||
<ActionPreviewHeader
|
<ActionPreviewHeader
|
||||||
tabs={renderedTabs}
|
tabs={(renderedTabs as unknown) as Tab<unknown, Action<unknown>>[]}
|
||||||
{...{ styling, inspectedPath, onInspectPath, tabName, onSelectTab }}
|
{...{ styling, inspectedPath, onInspectPath, tabName, onSelectTab }}
|
||||||
/>
|
/>
|
||||||
{!error && (
|
{!error && (
|
||||||
|
@ -94,7 +152,11 @@ class ActionPreview extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
labelRenderer = ([key, ...rest], nodeType, expanded) => {
|
labelRenderer = (
|
||||||
|
[key, ...rest]: (string | number)[],
|
||||||
|
nodeType: string,
|
||||||
|
expanded: boolean
|
||||||
|
) => {
|
||||||
const { styling, onInspectPath, inspectedPath } = this.props;
|
const { styling, onInspectPath, inspectedPath } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
import React from 'react';
|
import React, { FunctionComponent } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Action } from 'redux';
|
||||||
|
import { StylingFunction } from 'react-base16-styling';
|
||||||
|
import { Tab } from './ActionPreview';
|
||||||
|
|
||||||
const ActionPreviewHeader = ({
|
interface Props<S, A extends Action<unknown>> {
|
||||||
|
tabs: Tab<S, A>[];
|
||||||
|
styling: StylingFunction;
|
||||||
|
inspectedPath: (string | number)[];
|
||||||
|
onInspectPath: (path: (string | number)[]) => void;
|
||||||
|
tabName: string;
|
||||||
|
onSelectTab: (tabName: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ActionPreviewHeader: FunctionComponent<Props<
|
||||||
|
unknown,
|
||||||
|
Action<unknown>
|
||||||
|
>> = ({
|
||||||
styling,
|
styling,
|
||||||
inspectedPath,
|
inspectedPath,
|
||||||
onInspectPath,
|
onInspectPath,
|
||||||
|
@ -57,4 +73,13 @@ const ActionPreviewHeader = ({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ActionPreviewHeader.propTypes = {
|
||||||
|
tabs: PropTypes.array.isRequired,
|
||||||
|
styling: PropTypes.func.isRequired,
|
||||||
|
inspectedPath: PropTypes.array.isRequired,
|
||||||
|
onInspectPath: PropTypes.func.isRequired,
|
||||||
|
tabName: PropTypes.string.isRequired,
|
||||||
|
onSelectTab: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default ActionPreviewHeader;
|
export default ActionPreviewHeader;
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
base16Themes,
|
base16Themes,
|
||||||
} from './utils/createStylingFromTheme';
|
} from './utils/createStylingFromTheme';
|
||||||
import ActionList from './ActionList';
|
import ActionList from './ActionList';
|
||||||
import ActionPreview from './ActionPreview';
|
import ActionPreview, { Tab } from './ActionPreview';
|
||||||
import getInspectedState from './utils/getInspectedState';
|
import getInspectedState from './utils/getInspectedState';
|
||||||
import createDiffPatcher from './createDiffPatcher';
|
import createDiffPatcher from './createDiffPatcher';
|
||||||
import {
|
import {
|
||||||
|
@ -144,7 +144,7 @@ export interface DevtoolsInspectorProps<S, A extends Action<unknown>>
|
||||||
hideActionButtons?: boolean;
|
hideActionButtons?: boolean;
|
||||||
invertTheme: boolean;
|
invertTheme: boolean;
|
||||||
dataTypeKey?: string;
|
dataTypeKey?: string;
|
||||||
tabs: unknown;
|
tabs: Tab<S, A>[] | ((tabs: Tab<S, A>[]) => Tab<S, A>[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State<S, A extends Action<unknown>> {
|
interface State<S, A extends Action<unknown>> {
|
||||||
|
@ -342,7 +342,9 @@ export default class DevtoolsInspector<
|
||||||
monitorState={this.props.monitorState}
|
monitorState={this.props.monitorState}
|
||||||
updateMonitorState={this.updateMonitorState}
|
updateMonitorState={this.updateMonitorState}
|
||||||
styling={styling}
|
styling={styling}
|
||||||
onInspectPath={this.handleInspectPath.bind(this, inspectedPathType)}
|
onInspectPath={(path: (string | number)[]) =>
|
||||||
|
this.handleInspectPath(inspectedPathType, path)
|
||||||
|
}
|
||||||
inspectedPath={monitorState[inspectedPathType]}
|
inspectedPath={monitorState[inspectedPathType]}
|
||||||
onSelectTab={this.handleSelectTab}
|
onSelectTab={this.handleSelectTab}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,7 +1,20 @@
|
||||||
import React from 'react';
|
import React, { FunctionComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { StylingFunction } from 'react-base16-styling';
|
||||||
|
|
||||||
const RightSlider = ({ styling, shown, children, rotate }) => (
|
interface Props {
|
||||||
|
styling: StylingFunction;
|
||||||
|
shown?: boolean;
|
||||||
|
children: React.ReactNode;
|
||||||
|
rotate?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RightSlider: FunctionComponent<Props> = ({
|
||||||
|
styling,
|
||||||
|
shown,
|
||||||
|
children,
|
||||||
|
rotate,
|
||||||
|
}) => (
|
||||||
<div
|
<div
|
||||||
{...styling([
|
{...styling([
|
||||||
'rightSlider',
|
'rightSlider',
|
||||||
|
@ -15,7 +28,10 @@ const RightSlider = ({ styling, shown, children, rotate }) => (
|
||||||
);
|
);
|
||||||
|
|
||||||
RightSlider.propTypes = {
|
RightSlider.propTypes = {
|
||||||
|
styling: PropTypes.func.isRequired,
|
||||||
shown: PropTypes.bool,
|
shown: PropTypes.bool,
|
||||||
|
children: PropTypes.any.isRequired,
|
||||||
|
rotate: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RightSlider;
|
export default RightSlider;
|
||||||
|
|
|
@ -1,28 +1,37 @@
|
||||||
import { DiffPatcher } from 'jsondiffpatch';
|
import { DiffContext, DiffPatcher } from 'jsondiffpatch';
|
||||||
|
|
||||||
const defaultObjectHash = (o, idx) =>
|
const defaultObjectHash = (o: any, idx: number) =>
|
||||||
(o === null && '$$null') ||
|
(o === null && '$$null') ||
|
||||||
(o && (o.id || o.id === 0) && `$$id:${JSON.stringify(o.id)}`) ||
|
(o && (o.id || o.id === 0) && `$$id:${JSON.stringify(o.id)}`) ||
|
||||||
(o && (o._id || o._id === 0) && `$$_id:${JSON.stringify(o._id)}`) ||
|
(o && (o._id || o._id === 0) && `$$_id:${JSON.stringify(o._id)}`) ||
|
||||||
'$$index:' + idx;
|
`$$index:${idx}`;
|
||||||
|
|
||||||
const defaultPropertyFilter = (name, context) =>
|
const defaultPropertyFilter = (name: string, context: DiffContext) =>
|
||||||
typeof context.left[name] !== 'function' &&
|
typeof context.left[name] !== 'function' &&
|
||||||
typeof context.right[name] !== 'function';
|
typeof context.right[name] !== 'function';
|
||||||
|
|
||||||
const defaultDiffPatcher = new DiffPatcher({
|
const defaultDiffPatcher = new DiffPatcher({
|
||||||
arrays: { detectMove: false },
|
arrays: { detectMove: false } as {
|
||||||
|
detectMove: boolean;
|
||||||
|
includeValueOnMove: boolean;
|
||||||
|
},
|
||||||
objectHash: defaultObjectHash,
|
objectHash: defaultObjectHash,
|
||||||
propertyFilter: defaultPropertyFilter,
|
propertyFilter: defaultPropertyFilter,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function createDiffPatcher(objectHash, propertyFilter) {
|
export default function createDiffPatcher(
|
||||||
|
objectHash: ((item: unknown, index: number) => string) | undefined,
|
||||||
|
propertyFilter: ((name: string, context: DiffContext) => boolean) | undefined
|
||||||
|
) {
|
||||||
if (!objectHash && !propertyFilter) {
|
if (!objectHash && !propertyFilter) {
|
||||||
return defaultDiffPatcher;
|
return defaultDiffPatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DiffPatcher({
|
return new DiffPatcher({
|
||||||
arrays: { detectMove: false },
|
arrays: { detectMove: false } as {
|
||||||
|
detectMove: boolean;
|
||||||
|
includeValueOnMove: boolean;
|
||||||
|
},
|
||||||
objectHash: objectHash || defaultObjectHash,
|
objectHash: objectHash || defaultObjectHash,
|
||||||
propertyFilter: propertyFilter || defaultPropertyFilter,
|
propertyFilter: propertyFilter || defaultPropertyFilter,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
import React from 'react';
|
import React, { FunctionComponent } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import JSONTree from 'react-json-tree';
|
import JSONTree from 'react-json-tree';
|
||||||
|
import { Action } from 'redux';
|
||||||
import getItemString from './getItemString';
|
import getItemString from './getItemString';
|
||||||
import getJsonTreeTheme from './getJsonTreeTheme';
|
import getJsonTreeTheme from './getJsonTreeTheme';
|
||||||
|
import { TabComponentProps } from '../ActionPreview';
|
||||||
|
|
||||||
const ActionTab = ({
|
const ActionTab: FunctionComponent<TabComponentProps<
|
||||||
|
unknown,
|
||||||
|
Action<unknown>
|
||||||
|
>> = ({
|
||||||
action,
|
action,
|
||||||
styling,
|
styling,
|
||||||
base16Theme,
|
base16Theme,
|
||||||
|
@ -24,4 +30,14 @@ const ActionTab = ({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ActionTab.propTypes = {
|
||||||
|
action: PropTypes.any.isRequired,
|
||||||
|
styling: PropTypes.func.isRequired,
|
||||||
|
base16Theme: PropTypes.any.isRequired,
|
||||||
|
invertTheme: PropTypes.bool.isRequired,
|
||||||
|
labelRenderer: PropTypes.func.isRequired,
|
||||||
|
dataTypeKey: PropTypes.string,
|
||||||
|
isWideLayout: PropTypes.bool.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default ActionTab;
|
export default ActionTab;
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
import React from 'react';
|
import React, { FunctionComponent } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import JSONDiff from './JSONDiff';
|
import JSONDiff from './JSONDiff';
|
||||||
|
import { TabComponentProps } from '../ActionPreview';
|
||||||
|
import { Action } from 'redux';
|
||||||
|
|
||||||
const DiffTab = ({
|
const DiffTab: FunctionComponent<TabComponentProps<
|
||||||
|
unknown,
|
||||||
|
Action<unknown>
|
||||||
|
>> = ({
|
||||||
delta,
|
delta,
|
||||||
styling,
|
styling,
|
||||||
base16Theme,
|
base16Theme,
|
||||||
invertTheme,
|
invertTheme,
|
||||||
labelRenderer,
|
labelRenderer,
|
||||||
isWideLayout,
|
isWideLayout,
|
||||||
|
dataTypeKey,
|
||||||
}) => (
|
}) => (
|
||||||
<JSONDiff
|
<JSONDiff
|
||||||
{...{
|
{...{
|
||||||
|
@ -17,8 +24,19 @@ const DiffTab = ({
|
||||||
invertTheme,
|
invertTheme,
|
||||||
labelRenderer,
|
labelRenderer,
|
||||||
isWideLayout,
|
isWideLayout,
|
||||||
|
dataTypeKey,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DiffTab.propTypes = {
|
||||||
|
delta: PropTypes.any,
|
||||||
|
styling: PropTypes.func.isRequired,
|
||||||
|
base16Theme: PropTypes.any.isRequired,
|
||||||
|
invertTheme: PropTypes.bool.isRequired,
|
||||||
|
labelRenderer: PropTypes.func.isRequired,
|
||||||
|
isWideLayout: PropTypes.bool.isRequired,
|
||||||
|
dataTypeKey: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
export default DiffTab;
|
export default DiffTab;
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import JSONTree from 'react-json-tree';
|
import JSONTree from 'react-json-tree';
|
||||||
import { stringify } from 'javascript-stringify';
|
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 getItemString from './getItemString';
|
||||||
import getJsonTreeTheme from './getJsonTreeTheme';
|
import getJsonTreeTheme from './getJsonTreeTheme';
|
||||||
|
|
||||||
function stringifyAndShrink(val, isWideLayout) {
|
function stringifyAndShrink(val: any, isWideLayout?: boolean) {
|
||||||
if (val === null) {
|
if (val === null) {
|
||||||
return 'null';
|
return 'null';
|
||||||
}
|
}
|
||||||
|
@ -19,12 +22,16 @@ function stringifyAndShrink(val, isWideLayout) {
|
||||||
return str.length > 22 ? `${str.substr(0, 15)}…${str.substr(-5)}` : str;
|
return str.length > 22 ? `${str.substr(0, 15)}…${str.substr(-5)}` : str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const expandFirstLevel = (keyName, data, level) => level <= 1;
|
const expandFirstLevel = (
|
||||||
|
keyName: (string | number)[],
|
||||||
|
data: any,
|
||||||
|
level: number
|
||||||
|
) => level <= 1;
|
||||||
|
|
||||||
function prepareDelta(value) {
|
function prepareDelta(value: any) {
|
||||||
if (value && value._t === 'a') {
|
if (value && value._t === 'a') {
|
||||||
const res = {};
|
const res: { [key: string]: any } = {};
|
||||||
for (let key in value) {
|
for (const key in value) {
|
||||||
if (key !== '_t') {
|
if (key !== '_t') {
|
||||||
if (key[0] === '_' && !value[key.substr(1)]) {
|
if (key[0] === '_' && !value[key.substr(1)]) {
|
||||||
res[key.substr(1)] = value[key];
|
res[key.substr(1)] = value[key];
|
||||||
|
@ -41,14 +48,33 @@ function prepareDelta(value) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class JSONDiff extends Component {
|
interface Props {
|
||||||
state = { data: {} };
|
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 | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class JSONDiff extends Component<Props, State> {
|
||||||
|
state: State = { data: {} };
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.updateData();
|
this.updateData();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps: Props) {
|
||||||
if (prevProps.delta !== this.props.delta) {
|
if (prevProps.delta !== this.props.delta) {
|
||||||
this.updateData();
|
this.updateData();
|
||||||
}
|
}
|
||||||
|
@ -84,7 +110,7 @@ export default class JSONDiff extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getItemString = (type, data) =>
|
getItemString = (type: string, data: any) =>
|
||||||
getItemString(
|
getItemString(
|
||||||
this.props.styling,
|
this.props.styling,
|
||||||
type,
|
type,
|
||||||
|
@ -94,10 +120,10 @@ export default class JSONDiff extends Component {
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
valueRenderer = (raw, value) => {
|
valueRenderer = (raw: any, value: any) => {
|
||||||
const { styling, isWideLayout } = this.props;
|
const { styling, isWideLayout } = this.props;
|
||||||
|
|
||||||
function renderSpan(name, body) {
|
function renderSpan(name: string, body: string) {
|
||||||
return (
|
return (
|
||||||
<span key={name} {...styling(['diff', name])}>
|
<span key={name} {...styling(['diff', name])}>
|
||||||
{body}
|
{body}
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import JSONTree from 'react-json-tree';
|
import JSONTree from 'react-json-tree';
|
||||||
|
import { Action } from 'redux';
|
||||||
import getItemString from './getItemString';
|
import getItemString from './getItemString';
|
||||||
import getJsonTreeTheme from './getJsonTreeTheme';
|
import getJsonTreeTheme from './getJsonTreeTheme';
|
||||||
|
import { TabComponentProps } from '../ActionPreview';
|
||||||
|
|
||||||
const StateTab = ({
|
const StateTab: React.FunctionComponent<TabComponentProps<
|
||||||
|
any,
|
||||||
|
Action<unknown>
|
||||||
|
>> = ({
|
||||||
nextState,
|
nextState,
|
||||||
styling,
|
styling,
|
||||||
base16Theme,
|
base16Theme,
|
||||||
|
@ -24,4 +30,14 @@ const StateTab = ({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
StateTab.propTypes = {
|
||||||
|
nextState: PropTypes.any.isRequired,
|
||||||
|
styling: PropTypes.func.isRequired,
|
||||||
|
base16Theme: PropTypes.any.isRequired,
|
||||||
|
invertTheme: PropTypes.bool.isRequired,
|
||||||
|
labelRenderer: PropTypes.func.isRequired,
|
||||||
|
dataTypeKey: PropTypes.string,
|
||||||
|
isWideLayout: PropTypes.bool.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default StateTab;
|
export default StateTab;
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Iterable } from 'immutable';
|
import { isCollection, isIndexed, isKeyed } from 'immutable';
|
||||||
|
import { StylingFunction } from 'react-base16-styling';
|
||||||
import isIterable from '../utils/isIterable';
|
import isIterable from '../utils/isIterable';
|
||||||
|
|
||||||
const IS_IMMUTABLE_KEY = '@@__IS_IMMUTABLE__@@';
|
const IS_IMMUTABLE_KEY = '@@__IS_IMMUTABLE__@@';
|
||||||
|
|
||||||
function isImmutable(value) {
|
function isImmutable(value: any) {
|
||||||
return (
|
return isKeyed(value) || isIndexed(value) || isCollection(value);
|
||||||
Iterable.isKeyed(value) ||
|
|
||||||
Iterable.isIndexed(value) ||
|
|
||||||
Iterable.isIterable(value)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getShortTypeString(val, diff) {
|
function getShortTypeString(val: any, diff: boolean | undefined) {
|
||||||
if (diff && Array.isArray(val)) {
|
if (diff && Array.isArray(val)) {
|
||||||
val = val[val.length === 2 ? 1 : 0];
|
val = val[val.length === 2 ? 1 : 0];
|
||||||
}
|
}
|
||||||
|
@ -38,14 +35,21 @@ function getShortTypeString(val, diff) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getText(type, data, isWideLayout, isDiff) {
|
function getText(
|
||||||
|
type: string,
|
||||||
|
data: any,
|
||||||
|
isWideLayout: boolean,
|
||||||
|
isDiff: boolean | undefined
|
||||||
|
) {
|
||||||
if (type === 'Object') {
|
if (type === 'Object') {
|
||||||
const keys = Object.keys(data);
|
const keys = Object.keys(data);
|
||||||
if (!isWideLayout) return keys.length ? '{…}' : '{}';
|
if (!isWideLayout) return keys.length ? '{…}' : '{}';
|
||||||
|
|
||||||
const str = keys
|
const str = keys
|
||||||
.slice(0, 3)
|
.slice(0, 3)
|
||||||
.map((key) => `${key}: ${getShortTypeString(data[key], isDiff)}`)
|
.map(
|
||||||
|
(key) => `${key}: ${getShortTypeString(data[key], isDiff) as string}`
|
||||||
|
)
|
||||||
.concat(keys.length > 3 ? ['…'] : [])
|
.concat(keys.length > 3 ? ['…'] : [])
|
||||||
.join(', ');
|
.join(', ');
|
||||||
|
|
||||||
|
@ -55,27 +59,27 @@ function getText(type, data, isWideLayout, isDiff) {
|
||||||
|
|
||||||
const str = data
|
const str = data
|
||||||
.slice(0, 4)
|
.slice(0, 4)
|
||||||
.map((val) => getShortTypeString(val, isDiff))
|
.map((val: any) => getShortTypeString(val, isDiff))
|
||||||
.concat(data.length > 4 ? ['…'] : [])
|
.concat(data.length > 4 ? ['…'] : [])
|
||||||
.join(', ');
|
.join(', ');
|
||||||
|
|
||||||
return `[${str}]`;
|
return `[${str as string}]`;
|
||||||
} else {
|
} else {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getItemString = (
|
const getItemString = (
|
||||||
styling,
|
styling: StylingFunction,
|
||||||
type,
|
type: string,
|
||||||
data,
|
data: any,
|
||||||
dataTypeKey,
|
dataTypeKey: string | undefined,
|
||||||
isWideLayout,
|
isWideLayout: boolean,
|
||||||
isDiff
|
isDiff?: boolean
|
||||||
) => (
|
) => (
|
||||||
<span {...styling('treeItemHint')}>
|
<span {...styling('treeItemHint')}>
|
||||||
{data[IS_IMMUTABLE_KEY] ? 'Immutable' : ''}
|
{data[IS_IMMUTABLE_KEY] ? 'Immutable' : ''}
|
||||||
{dataTypeKey && data[dataTypeKey] ? data[dataTypeKey] + ' ' : ''}
|
{dataTypeKey && data[dataTypeKey] ? `${data[dataTypeKey] as string} ` : ''}
|
||||||
{getText(type, data, isWideLayout, isDiff)}
|
{getText(type, data, isWideLayout, isDiff)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
export default function getJsonTreeTheme(base16Theme) {
|
import { Base16Theme } from 'base16';
|
||||||
|
import { StylingConfig } from 'react-base16-styling';
|
||||||
|
|
||||||
|
export default function getJsonTreeTheme(
|
||||||
|
base16Theme: Base16Theme
|
||||||
|
): StylingConfig {
|
||||||
return {
|
return {
|
||||||
extend: base16Theme,
|
extend: base16Theme,
|
||||||
nestedNode: ({ style }, keyPath, nodeType, expanded) => ({
|
nestedNode: ({ style }, keyPath, nodeType, expanded) => ({
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import jss from 'jss';
|
import jss, { Styles, StyleSheet } from 'jss';
|
||||||
import preset from 'jss-preset-default';
|
import preset from 'jss-preset-default';
|
||||||
import { createStyling } from 'react-base16-styling';
|
import { createStyling } from 'react-base16-styling';
|
||||||
import rgba from 'hex-rgba';
|
import rgba from 'hex-rgba';
|
||||||
|
import { Base16Theme } from 'redux-devtools-themes';
|
||||||
import inspector from '../themes/inspector';
|
import inspector from '../themes/inspector';
|
||||||
import * as reduxThemes from 'redux-devtools-themes';
|
import * as reduxThemes from 'redux-devtools-themes';
|
||||||
import * as inspectorThemes from '../themes';
|
import * as inspectorThemes from '../themes';
|
||||||
|
|
||||||
jss.setup(preset());
|
jss.setup(preset());
|
||||||
|
|
||||||
const colorMap = (theme) => ({
|
const colorMap = (theme: Base16Theme) => ({
|
||||||
TEXT_COLOR: theme.base06,
|
TEXT_COLOR: theme.base06,
|
||||||
TEXT_PLACEHOLDER_COLOR: rgba(theme.base06, 60),
|
TEXT_PLACEHOLDER_COLOR: rgba(theme.base06, 60),
|
||||||
BACKGROUND_COLOR: theme.base00,
|
BACKGROUND_COLOR: theme.base00,
|
||||||
|
@ -34,7 +35,12 @@ const colorMap = (theme) => ({
|
||||||
ERROR_COLOR: theme.base08,
|
ERROR_COLOR: theme.base08,
|
||||||
});
|
});
|
||||||
|
|
||||||
const getSheetFromColorMap = (map) => ({
|
type Color = keyof ReturnType<typeof colorMap>;
|
||||||
|
type ColorMap = {
|
||||||
|
[color in Color]: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSheetFromColorMap = (map: ColorMap) => ({
|
||||||
inspector: {
|
inspector: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
'flex-direction': 'column',
|
'flex-direction': 'column',
|
||||||
|
@ -384,9 +390,9 @@ const getSheetFromColorMap = (map) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let themeSheet;
|
let themeSheet: StyleSheet;
|
||||||
|
|
||||||
const getDefaultThemeStyling = (theme) => {
|
const getDefaultThemeStyling = (theme: Base16Theme) => {
|
||||||
if (themeSheet) {
|
if (themeSheet) {
|
||||||
themeSheet.detach();
|
themeSheet.detach();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
function deepMapCached(obj, f, ctx, cache) {
|
|
||||||
cache.push(obj);
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
return obj.map(function (val, key) {
|
|
||||||
val = f.call(ctx, val, key);
|
|
||||||
return typeof val === 'object' && cache.indexOf(val) === -1
|
|
||||||
? deepMapCached(val, f, ctx, cache)
|
|
||||||
: val;
|
|
||||||
});
|
|
||||||
} else if (typeof obj === 'object') {
|
|
||||||
const res = {};
|
|
||||||
for (const key in obj) {
|
|
||||||
let val = obj[key];
|
|
||||||
if (val && typeof val === 'object') {
|
|
||||||
val = f.call(ctx, val, key);
|
|
||||||
res[key] =
|
|
||||||
cache.indexOf(val) === -1 ? deepMapCached(val, f, ctx, cache) : val;
|
|
||||||
} else {
|
|
||||||
res[key] = f.call(ctx, val, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
} else {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function deepMap(obj, f, ctx) {
|
|
||||||
return deepMapCached(obj, f, ctx, []);
|
|
||||||
}
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Iterable, fromJS } from 'immutable';
|
import { fromJS, isAssociative } from 'immutable';
|
||||||
import isIterable from './isIterable';
|
import isIterable from './isIterable';
|
||||||
|
|
||||||
function iterateToKey(obj, key) {
|
function iterateToKey(obj: any, key: string | number) {
|
||||||
// maybe there's a better way, dunno
|
// maybe there's a better way, dunno
|
||||||
let idx = 0;
|
let idx = 0;
|
||||||
for (let entry of obj) {
|
for (const entry of obj) {
|
||||||
if (Array.isArray(entry)) {
|
if (Array.isArray(entry)) {
|
||||||
if (entry[0] === key) return entry[1];
|
if (entry[0] === key) return entry[1];
|
||||||
} else {
|
} else {
|
||||||
|
@ -15,24 +15,28 @@ function iterateToKey(obj, key) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getInspectedState(state, path, convertImmutable) {
|
export default function getInspectedState<S>(
|
||||||
|
state: S,
|
||||||
|
path: (string | number)[],
|
||||||
|
convertImmutable: boolean
|
||||||
|
): S {
|
||||||
state =
|
state =
|
||||||
path && path.length
|
path && path.length
|
||||||
? {
|
? ({
|
||||||
[path[path.length - 1]]: path.reduce((s, key) => {
|
[path[path.length - 1]]: path.reduce((s: any, key) => {
|
||||||
if (!s) {
|
if (!s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Iterable.isAssociative(s)) {
|
if (isAssociative(s)) {
|
||||||
return s.get(key);
|
return s.get(key as number);
|
||||||
} else if (isIterable(s)) {
|
} else if (isIterable(s)) {
|
||||||
return iterateToKey(s, key);
|
return iterateToKey(s, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return s[key];
|
return s[key];
|
||||||
}, state),
|
}, state),
|
||||||
}
|
} as S)
|
||||||
: state;
|
: state;
|
||||||
|
|
||||||
if (convertImmutable) {
|
if (convertImmutable) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export default function isIterable(obj) {
|
export default function isIterable(obj: any) {
|
||||||
return (
|
return (
|
||||||
obj !== null &&
|
obj !== null &&
|
||||||
typeof obj === 'object' &&
|
typeof obj === 'object' &&
|
||||||
|
|
|
@ -9,7 +9,6 @@ const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: process.env.NODE_ENV || 'development',
|
mode: process.env.NODE_ENV || 'development',
|
||||||
devtool: 'eval-source-map',
|
|
||||||
entry: isProduction
|
entry: isProduction
|
||||||
? ['./demo/src/js/index']
|
? ['./demo/src/js/index']
|
||||||
: [
|
: [
|
||||||
|
@ -21,26 +20,10 @@ module.exports = {
|
||||||
path: path.join(__dirname, 'demo/dist'),
|
path: path.join(__dirname, 'demo/dist'),
|
||||||
filename: 'js/bundle.js',
|
filename: 'js/bundle.js',
|
||||||
},
|
},
|
||||||
plugins: [
|
|
||||||
new CleanWebpackPlugin(),
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
inject: true,
|
|
||||||
template: 'demo/src/index.html',
|
|
||||||
package: pkg,
|
|
||||||
}),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env': {
|
|
||||||
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
].concat(isProduction ? [] : [new webpack.HotModuleReplacementPlugin()]),
|
|
||||||
resolve: {
|
|
||||||
extensions: ['*', '.js', '.jsx'],
|
|
||||||
},
|
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.jsx?$/,
|
test: /\.(js|ts)x?$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
include: [
|
include: [
|
||||||
path.join(__dirname, 'src'),
|
path.join(__dirname, 'src'),
|
||||||
|
@ -49,6 +32,17 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['*', '.js', '.jsx'],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new CleanWebpackPlugin(),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
inject: true,
|
||||||
|
template: 'demo/src/index.html',
|
||||||
|
package: pkg,
|
||||||
|
}),
|
||||||
|
].concat(isProduction ? [] : [new webpack.HotModuleReplacementPlugin()]),
|
||||||
devServer: isProduction
|
devServer: isProduction
|
||||||
? {}
|
? {}
|
||||||
: {
|
: {
|
||||||
|
@ -61,4 +55,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
historyApiFallback: true,
|
historyApiFallback: true,
|
||||||
},
|
},
|
||||||
|
devtool: 'eval-source-map',
|
||||||
};
|
};
|
||||||
|
|
|
@ -3131,6 +3131,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/hex-rgba@^1.0.0":
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/hex-rgba/-/hex-rgba-1.0.0.tgz#b2aed2aa9fdd6152b7f0ac5e3733b974d4eba35a"
|
||||||
|
integrity sha512-u3AGV8fjRsDBqY4wOvVWhVCgKDfh2b0h3mux7KPKU1cm/6mJp14OWBINLgBypeBTM89Nm2j+eKQqIoIe7150DA==
|
||||||
|
|
||||||
"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0":
|
"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0":
|
||||||
version "3.3.1"
|
version "3.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
|
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user