mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-25 19:13:56 +03:00
* fix: broken rtk-query-monitor demo not working #1126 Description: downgrades framer-motion in order to remove the runtime error "_framerMotion.motion.custom is not a function" See: https://stackoverflow.com/questions/66703410/next-js-framermotion-motion-custom-is-not-a-function * feat(rtk-query): add Data tab #1126 * fix: bump min popup width to 700px #1126 Description: improve UI of rtk-query right side tabs * fix: bump min popup window width again to 760px #1126 * chore: add changeset * feat(rtk-query): improve a11y of rtk-query-monitor tab panel #1126 * chore(rtk-query): add few integration tests to rtk-query-monitor #1126 * Fix merge * Deduplicate msw Co-authored-by: Nathan Bierema <nbierema@gmail.com>
This commit is contained in:
parent
6cf1865f55
commit
24f60a7aa7
5
.changeset/lemon-balloons-sniff.md
Normal file
5
.changeset/lemon-balloons-sniff.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@redux-devtools/rtk-query-monitor': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(rtk-query): add Data tab to rtk-query-monitor #1126 #1129
|
5
.changeset/popular-dodos-laugh.md
Normal file
5
.changeset/popular-dodos-laugh.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'rtk-query-demo': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: rtk-query-monitor demo not working #1126 #1129
|
5
.changeset/ten-files-return.md
Normal file
5
.changeset/ten-files-return.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'remotedev-redux-devtools-extension': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
bump min popup window width to 760px #1126 #1129
|
|
@ -7,7 +7,7 @@ style.
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 350px;
|
min-width: 760px;
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -17,6 +17,7 @@ style.
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
#root {
|
#root {
|
||||||
|
min-width: 760px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
#root > div {
|
#root > div {
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
demo
|
demo
|
||||||
lib
|
lib
|
||||||
|
dist
|
||||||
|
|
|
@ -9,5 +9,13 @@ module.exports = {
|
||||||
project: ['./tsconfig.json'],
|
project: ['./tsconfig.json'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: ['test/**/*.ts', 'test/**/*.tsx'],
|
||||||
|
extends: '../../eslintrc.ts.react.jest.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.test.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
"@redux-devtools/rtk-query-monitor": "^3.0.0",
|
"@redux-devtools/rtk-query-monitor": "^3.0.0",
|
||||||
"@reduxjs/toolkit": "^1.8.2",
|
"@reduxjs/toolkit": "^1.8.2",
|
||||||
"framer-motion": "^6.3.15",
|
"framer-motion": "^6.3.15",
|
||||||
"msw": "^0.42.3",
|
"msw": "^0.43.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^4.4.0",
|
"react-icons": "^4.4.0",
|
||||||
|
|
12
packages/redux-devtools-rtk-query-monitor/jest.config.js
Normal file
12
packages/redux-devtools-rtk-query-monitor/jest.config.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
moduleNameMapper: {
|
||||||
|
'\\.css$': '<rootDir>/test/__mocks__/styleMock.ts',
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
'ts-jest': {
|
||||||
|
tsconfig: 'tsconfig.test.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
|
@ -37,10 +37,11 @@
|
||||||
"build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts,.tsx\" --out-dir lib/esm",
|
"build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts,.tsx\" --out-dir lib/esm",
|
||||||
"build:types": "tsc --emitDeclarationOnly",
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
"clean": "rimraf lib",
|
"clean": "rimraf lib",
|
||||||
|
"test": "jest",
|
||||||
"lint": "eslint . --ext .ts,.tsx",
|
"lint": "eslint . --ext .ts,.tsx",
|
||||||
"type-check": "tsc --noEmit",
|
"type-check": "tsc --noEmit",
|
||||||
"prepack": "pnpm run clean && pnpm run build",
|
"prepack": "pnpm run clean && pnpm run build",
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint"
|
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.18.3",
|
"@babel/runtime": "^7.18.3",
|
||||||
|
@ -68,6 +69,9 @@
|
||||||
"@babel/preset-typescript": "^7.17.12",
|
"@babel/preset-typescript": "^7.17.12",
|
||||||
"@redux-devtools/core": "^3.13.1",
|
"@redux-devtools/core": "^3.13.1",
|
||||||
"@reduxjs/toolkit": "^1.8.2",
|
"@reduxjs/toolkit": "^1.8.2",
|
||||||
|
"@testing-library/jest-dom": "^5.16.4",
|
||||||
|
"@testing-library/react": "^13.3.0",
|
||||||
|
"@types/jest": "^27.5.2",
|
||||||
"@types/hex-rgba": "^1.0.1",
|
"@types/hex-rgba": "^1.0.1",
|
||||||
"@types/lodash.debounce": "^4.0.7",
|
"@types/lodash.debounce": "^4.0.7",
|
||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
|
@ -75,11 +79,16 @@
|
||||||
"@typescript-eslint/parser": "^5.29.0",
|
"@typescript-eslint/parser": "^5.29.0",
|
||||||
"eslint": "^8.18.0",
|
"eslint": "^8.18.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
|
"eslint-plugin-jest": "^26.5.3",
|
||||||
"eslint-plugin-react": "^7.30.1",
|
"eslint-plugin-react": "^7.30.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"jest": "^27.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-redux": "^8.0.2",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
|
"ts-jest": "^27.1.5",
|
||||||
"typescript": "~4.7.4"
|
"typescript": "~4.7.4"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|
|
@ -128,6 +128,7 @@ export class QueryForm extends React.PureComponent<
|
||||||
{({ styling, base16Theme }) => {
|
{({ styling, base16Theme }) => {
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
|
id="rtk-query-monitor-query-selection-form"
|
||||||
action="#"
|
action="#"
|
||||||
onSubmit={this.handleSubmit}
|
onSubmit={this.handleSubmit}
|
||||||
{...styling('queryForm')}
|
{...styling('queryForm')}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { createSelector, Selector } from '@reduxjs/toolkit';
|
import { createSelector, Selector } from '@reduxjs/toolkit';
|
||||||
import React, { ReactNode, PureComponent } from 'react';
|
import React, { ReactNode, PureComponent } from 'react';
|
||||||
import { Action, AnyAction } from 'redux';
|
import { Action, AnyAction } from 'redux';
|
||||||
|
import { QueryPreviewTabs } from '../types';
|
||||||
|
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||||
import { emptyRecord, identity } from '../utils/object';
|
import { emptyRecord, identity } from '../utils/object';
|
||||||
import { TreeView } from './TreeView';
|
import { TreeView, TreeViewProps } from './TreeView';
|
||||||
|
|
||||||
export interface QueryPreviewActionsProps {
|
export interface QueryPreviewActionsProps {
|
||||||
isWideLayout: boolean;
|
isWideLayout: boolean;
|
||||||
|
@ -11,6 +13,12 @@ export interface QueryPreviewActionsProps {
|
||||||
|
|
||||||
const keySep = ' - ';
|
const keySep = ' - ';
|
||||||
|
|
||||||
|
const rootProps: TreeViewProps['rootProps'] = {
|
||||||
|
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.actions),
|
||||||
|
id: renderTabPanelId(QueryPreviewTabs.actions),
|
||||||
|
role: 'tabpanel',
|
||||||
|
};
|
||||||
|
|
||||||
export class QueryPreviewActions extends PureComponent<QueryPreviewActionsProps> {
|
export class QueryPreviewActions extends PureComponent<QueryPreviewActionsProps> {
|
||||||
selectFormattedActions: Selector<
|
selectFormattedActions: Selector<
|
||||||
AnyAction[],
|
AnyAction[],
|
||||||
|
@ -74,6 +82,7 @@ export class QueryPreviewActions extends PureComponent<QueryPreviewActionsProps>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TreeView
|
<TreeView
|
||||||
|
rootProps={rootProps}
|
||||||
data={this.selectFormattedActions(actionsOfQuery)}
|
data={this.selectFormattedActions(actionsOfQuery)}
|
||||||
isWideLayout={isWideLayout}
|
isWideLayout={isWideLayout}
|
||||||
shouldExpandNode={this.shouldExpandNode}
|
shouldExpandNode={this.shouldExpandNode}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React, { ReactNode, PureComponent } from 'react';
|
import React, { ReactNode, PureComponent } from 'react';
|
||||||
import { ApiStats, RtkQueryApiState } from '../types';
|
import { ApiStats, QueryPreviewTabs, RtkQueryApiState } from '../types';
|
||||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||||
import { TreeView } from './TreeView';
|
import { TreeView, TreeViewProps } from './TreeView';
|
||||||
|
import { renderTabPanelId, renderTabPanelButtonId } from '../utils/a11y';
|
||||||
|
|
||||||
export interface QueryPreviewApiProps {
|
export interface QueryPreviewApiProps {
|
||||||
apiStats: ApiStats | null;
|
apiStats: ApiStats | null;
|
||||||
|
@ -9,6 +10,12 @@ export interface QueryPreviewApiProps {
|
||||||
isWideLayout: boolean;
|
isWideLayout: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rootProps: TreeViewProps['rootProps'] = {
|
||||||
|
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.apiConfig),
|
||||||
|
id: renderTabPanelId(QueryPreviewTabs.apiConfig),
|
||||||
|
role: 'tabpanel',
|
||||||
|
};
|
||||||
|
|
||||||
export class QueryPreviewApi extends PureComponent<QueryPreviewApiProps> {
|
export class QueryPreviewApi extends PureComponent<QueryPreviewApiProps> {
|
||||||
shouldExpandApiStateNode = (
|
shouldExpandApiStateNode = (
|
||||||
keyPath: (string | number)[],
|
keyPath: (string | number)[],
|
||||||
|
@ -33,7 +40,7 @@ export class QueryPreviewApi extends PureComponent<QueryPreviewApiProps> {
|
||||||
return (
|
return (
|
||||||
<StyleUtilsContext.Consumer>
|
<StyleUtilsContext.Consumer>
|
||||||
{({ styling }) => (
|
{({ styling }) => (
|
||||||
<article {...styling('tabContent')}>
|
<article {...rootProps} {...styling('tabContent')}>
|
||||||
<h2>{apiState.config.reducerPath}</h2>
|
<h2>{apiState.config.reducerPath}</h2>
|
||||||
<TreeView
|
<TreeView
|
||||||
before={<h3>State</h3>}
|
before={<h3>State</h3>}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import React, { ReactNode, PureComponent } from 'react';
|
||||||
|
import { QueryPreviewTabs, RtkResourceInfo } from '../types';
|
||||||
|
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||||
|
import { TreeView, TreeViewProps } from './TreeView';
|
||||||
|
|
||||||
|
export interface QueryPreviewDataProps {
|
||||||
|
data: RtkResourceInfo['state']['data'];
|
||||||
|
isWideLayout: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootProps: TreeViewProps['rootProps'] = {
|
||||||
|
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.data),
|
||||||
|
id: renderTabPanelId(QueryPreviewTabs.data),
|
||||||
|
role: 'tabpanel',
|
||||||
|
};
|
||||||
|
|
||||||
|
export class QueryPreviewData extends PureComponent<QueryPreviewDataProps> {
|
||||||
|
shouldExpandNode = (
|
||||||
|
keyPath: (string | number)[],
|
||||||
|
value: unknown,
|
||||||
|
layer: number
|
||||||
|
): boolean => {
|
||||||
|
return layer <= 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
const { data, isWideLayout } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TreeView
|
||||||
|
rootProps={rootProps}
|
||||||
|
data={data}
|
||||||
|
isWideLayout={isWideLayout}
|
||||||
|
shouldExpandNode={this.shouldExpandNode}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { ReactNode } from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||||
import { QueryPreviewTabs, TabOption } from '../types';
|
import { QueryPreviewTabs, TabOption } from '../types';
|
||||||
|
import { renderTabPanelButtonId } from '../utils/a11y';
|
||||||
import { emptyArray } from '../utils/object';
|
import { emptyArray } from '../utils/object';
|
||||||
|
|
||||||
export interface QueryPreviewHeaderProps {
|
export interface QueryPreviewHeaderProps {
|
||||||
|
@ -28,7 +29,11 @@ export class QueryPreviewHeader extends React.Component<QueryPreviewHeaderProps>
|
||||||
<div {...styling('previewHeader')}>
|
<div {...styling('previewHeader')}>
|
||||||
<div {...styling('tabSelector')}>
|
<div {...styling('tabSelector')}>
|
||||||
{tabs.map((tab) => (
|
{tabs.map((tab) => (
|
||||||
<div
|
<button
|
||||||
|
type="button"
|
||||||
|
id={renderTabPanelButtonId(tab.value)}
|
||||||
|
aria-selected={tab.value === selectedTab}
|
||||||
|
role={'tab'}
|
||||||
onClick={() => this.handleTabClick(tab)}
|
onClick={() => this.handleTabClick(tab)}
|
||||||
key={tab.value}
|
key={tab.value}
|
||||||
{...styling(
|
{...styling(
|
||||||
|
@ -42,7 +47,7 @@ export class QueryPreviewHeader extends React.Component<QueryPreviewHeaderProps>
|
||||||
<span>
|
<span>
|
||||||
{renderTabLabel ? renderTabLabel(tab) : tab.label}
|
{renderTabLabel ? renderTabLabel(tab) : tab.label}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { createSelector, Selector } from '@reduxjs/toolkit';
|
import { createSelector, Selector } from '@reduxjs/toolkit';
|
||||||
import { QueryStatus } from '@reduxjs/toolkit/dist/query';
|
import { QueryStatus } from '@reduxjs/toolkit/dist/query';
|
||||||
import React, { ReactNode, PureComponent } from 'react';
|
import React, { ReactNode, PureComponent } from 'react';
|
||||||
import { RtkResourceInfo, RTKStatusFlags } from '../types';
|
import { QueryPreviewTabs, RtkResourceInfo, RTKStatusFlags } from '../types';
|
||||||
|
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||||
import { formatMs } from '../utils/formatters';
|
import { formatMs } from '../utils/formatters';
|
||||||
import { identity } from '../utils/object';
|
import { identity } from '../utils/object';
|
||||||
import { getQueryStatusFlags } from '../utils/rtk-query';
|
import { getQueryStatusFlags } from '../utils/rtk-query';
|
||||||
import { TreeView } from './TreeView';
|
import { TreeView, TreeViewProps } from './TreeView';
|
||||||
|
|
||||||
type QueryTimings = {
|
type QueryTimings = {
|
||||||
startedAt: string;
|
startedAt: string;
|
||||||
|
@ -23,6 +24,12 @@ type FormattedQuery = {
|
||||||
| { query: RtkResourceInfo['state'] }
|
| { query: RtkResourceInfo['state'] }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const rootProps: TreeViewProps['rootProps'] = {
|
||||||
|
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.queryinfo),
|
||||||
|
id: renderTabPanelId(QueryPreviewTabs.queryinfo),
|
||||||
|
role: 'tabpanel',
|
||||||
|
};
|
||||||
|
|
||||||
export interface QueryPreviewInfoProps {
|
export interface QueryPreviewInfoProps {
|
||||||
resInfo: RtkResourceInfo;
|
resInfo: RtkResourceInfo;
|
||||||
isWideLayout: boolean;
|
isWideLayout: boolean;
|
||||||
|
@ -97,6 +104,7 @@ export class QueryPreviewInfo extends PureComponent<QueryPreviewInfoProps> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TreeView
|
<TreeView
|
||||||
|
rootProps={rootProps}
|
||||||
data={formattedQuery}
|
data={formattedQuery}
|
||||||
isWideLayout={isWideLayout}
|
isWideLayout={isWideLayout}
|
||||||
shouldExpandNode={this.shouldExpandNode}
|
shouldExpandNode={this.shouldExpandNode}
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
import React, { ReactNode, PureComponent } from 'react';
|
import React, { ReactNode, PureComponent } from 'react';
|
||||||
import { RtkQueryApiState } from '../types';
|
import { QueryPreviewTabs, RtkQueryApiState } from '../types';
|
||||||
import { TreeView } from './TreeView';
|
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||||
|
import { TreeView, TreeViewProps } from './TreeView';
|
||||||
|
|
||||||
|
const rootProps: TreeViewProps['rootProps'] = {
|
||||||
|
'aria-labelledby': renderTabPanelButtonId(
|
||||||
|
QueryPreviewTabs.querySubscriptions
|
||||||
|
),
|
||||||
|
id: renderTabPanelId(QueryPreviewTabs.querySubscriptions),
|
||||||
|
role: 'tabpanel',
|
||||||
|
};
|
||||||
|
|
||||||
export interface QueryPreviewSubscriptionsProps {
|
export interface QueryPreviewSubscriptionsProps {
|
||||||
subscriptions: RtkQueryApiState['subscriptions'][keyof RtkQueryApiState['subscriptions']];
|
subscriptions: RtkQueryApiState['subscriptions'][keyof RtkQueryApiState['subscriptions']];
|
||||||
|
@ -12,7 +21,11 @@ export class QueryPreviewSubscriptions extends PureComponent<QueryPreviewSubscri
|
||||||
const { subscriptions } = this.props;
|
const { subscriptions } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TreeView data={subscriptions} isWideLayout={this.props.isWideLayout} />
|
<TreeView
|
||||||
|
rootProps={rootProps}
|
||||||
|
data={subscriptions}
|
||||||
|
isWideLayout={this.props.isWideLayout}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
import React, { ReactNode, PureComponent } from 'react';
|
import React, { ReactNode, PureComponent } from 'react';
|
||||||
import { RtkQueryTag } from '../types';
|
import { QueryPreviewTabs, RtkQueryTag } from '../types';
|
||||||
import { TreeView } from './TreeView';
|
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||||
|
import { TreeView, TreeViewProps } from './TreeView';
|
||||||
|
|
||||||
interface QueryPreviewTagsState {
|
interface QueryPreviewTagsState {
|
||||||
data: { tags: RtkQueryTag[] };
|
data: { tags: RtkQueryTag[] };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rootProps: TreeViewProps['rootProps'] = {
|
||||||
|
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.queryTags),
|
||||||
|
id: renderTabPanelId(QueryPreviewTabs.queryTags),
|
||||||
|
role: 'tabpanel',
|
||||||
|
};
|
||||||
|
|
||||||
export interface QueryPreviewTagsProps {
|
export interface QueryPreviewTagsProps {
|
||||||
tags: RtkQueryTag[];
|
tags: RtkQueryTag[];
|
||||||
isWideLayout: boolean;
|
isWideLayout: boolean;
|
||||||
|
@ -26,6 +33,8 @@ export class QueryPreviewTags extends PureComponent<
|
||||||
render(): ReactNode {
|
render(): ReactNode {
|
||||||
const { isWideLayout, tags } = this.props;
|
const { isWideLayout, tags } = this.props;
|
||||||
|
|
||||||
return <TreeView data={tags} isWideLayout={isWideLayout} />;
|
return (
|
||||||
|
<TreeView rootProps={rootProps} data={tags} isWideLayout={isWideLayout} />
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@ export interface TreeViewProps
|
||||||
before?: ReactNode;
|
before?: ReactNode;
|
||||||
after?: ReactNode;
|
after?: ReactNode;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
|
rootProps?: Partial<
|
||||||
|
Omit<React.HTMLAttributes<HTMLDivElement>, 'className' | 'style'>
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TreeView extends React.PureComponent<TreeViewProps> {
|
export class TreeView extends React.PureComponent<TreeViewProps> {
|
||||||
|
@ -80,13 +83,14 @@ export class TreeView extends React.PureComponent<TreeViewProps> {
|
||||||
keyPath,
|
keyPath,
|
||||||
shouldExpandNode,
|
shouldExpandNode,
|
||||||
hideRoot,
|
hideRoot,
|
||||||
|
rootProps,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyleUtilsContext.Consumer>
|
<StyleUtilsContext.Consumer>
|
||||||
{({ styling, invertTheme, base16Theme }) => {
|
{({ styling, invertTheme, base16Theme }) => {
|
||||||
return (
|
return (
|
||||||
<div {...styling('treeWrapper')}>
|
<div {...rootProps} {...styling('treeWrapper')}>
|
||||||
{before}
|
{before}
|
||||||
<JSONTree
|
<JSONTree
|
||||||
keyPath={keyPath}
|
keyPath={keyPath}
|
||||||
|
|
|
@ -33,6 +33,10 @@ import {
|
||||||
QueryPreviewActionsProps,
|
QueryPreviewActionsProps,
|
||||||
} from '../components/QueryPreviewActions';
|
} from '../components/QueryPreviewActions';
|
||||||
import { isTabVisible } from '../utils/tabs';
|
import { isTabVisible } from '../utils/tabs';
|
||||||
|
import {
|
||||||
|
QueryPreviewData,
|
||||||
|
QueryPreviewDataProps,
|
||||||
|
} from '../components/QueryPreviewData';
|
||||||
|
|
||||||
export interface QueryPreviewProps<S = unknown> {
|
export interface QueryPreviewProps<S = unknown> {
|
||||||
readonly selectedTab: QueryPreviewTabs;
|
readonly selectedTab: QueryPreviewTabs;
|
||||||
|
@ -66,6 +70,14 @@ const MappedQueryPreviewInfo = mapProps<
|
||||||
QueryPreviewInfoProps
|
QueryPreviewInfoProps
|
||||||
>(({ resInfo, isWideLayout }) => ({ resInfo, isWideLayout }))(QueryPreviewInfo);
|
>(({ resInfo, isWideLayout }) => ({ resInfo, isWideLayout }))(QueryPreviewInfo);
|
||||||
|
|
||||||
|
const MappedQueryPreviewData = mapProps<
|
||||||
|
QueryPreviewTabProps,
|
||||||
|
QueryPreviewDataProps
|
||||||
|
>(({ resInfo, isWideLayout }) => ({
|
||||||
|
data: resInfo?.state?.data,
|
||||||
|
isWideLayout,
|
||||||
|
}))(QueryPreviewData);
|
||||||
|
|
||||||
const MappedQuerySubscriptipns = mapProps<
|
const MappedQuerySubscriptipns = mapProps<
|
||||||
QueryPreviewTabProps,
|
QueryPreviewTabProps,
|
||||||
QueryPreviewSubscriptionsProps
|
QueryPreviewSubscriptionsProps
|
||||||
|
@ -93,6 +105,16 @@ const MappedQueryPreviewActions = mapProps<
|
||||||
const tabs: ReadonlyArray<
|
const tabs: ReadonlyArray<
|
||||||
TabOption<QueryPreviewTabs, QueryPreviewTabProps, RtkResourceInfo['type']>
|
TabOption<QueryPreviewTabs, QueryPreviewTabProps, RtkResourceInfo['type']>
|
||||||
> = [
|
> = [
|
||||||
|
{
|
||||||
|
label: 'Data',
|
||||||
|
value: QueryPreviewTabs.data,
|
||||||
|
component: MappedQueryPreviewData,
|
||||||
|
visible: {
|
||||||
|
query: true,
|
||||||
|
mutation: true,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Query',
|
label: 'Query',
|
||||||
value: QueryPreviewTabs.queryinfo,
|
value: QueryPreviewTabs.queryinfo,
|
||||||
|
|
|
@ -258,6 +258,7 @@ export function createInspectorSelectors<S>(): InspectorSelectors<S> {
|
||||||
],
|
],
|
||||||
(subscriptions, actions, tags) => {
|
(subscriptions, actions, tags) => {
|
||||||
return {
|
return {
|
||||||
|
[QueryPreviewTabs.data]: 0,
|
||||||
[QueryPreviewTabs.queryTags]: tags.length,
|
[QueryPreviewTabs.queryTags]: tags.length,
|
||||||
[QueryPreviewTabs.querySubscriptions]: Object.keys(subscriptions ?? {})
|
[QueryPreviewTabs.querySubscriptions]: Object.keys(subscriptions ?? {})
|
||||||
.length,
|
.length,
|
||||||
|
|
|
@ -220,6 +220,8 @@ const getSheetFromColorMap = (map: ColorMap) => {
|
||||||
padding: '0 8px',
|
padding: '0 8px',
|
||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
boxShadow: 'none',
|
||||||
|
outline: 'none',
|
||||||
color: map.TEXT_COLOR,
|
color: map.TEXT_COLOR,
|
||||||
'border-style': 'solid',
|
'border-style': 'solid',
|
||||||
'border-width': '1px',
|
'border-width': '1px',
|
||||||
|
|
|
@ -8,6 +8,7 @@ import type { QueryComparators } from './utils/comparators';
|
||||||
import type { QueryFilters } from './utils/filters';
|
import type { QueryFilters } from './utils/filters';
|
||||||
|
|
||||||
export enum QueryPreviewTabs {
|
export enum QueryPreviewTabs {
|
||||||
|
data,
|
||||||
queryinfo,
|
queryinfo,
|
||||||
apiConfig,
|
apiConfig,
|
||||||
querySubscriptions,
|
querySubscriptions,
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { QueryPreviewTabs } from '../types';
|
||||||
|
|
||||||
|
export function renderTabPanelId(value: QueryPreviewTabs): string {
|
||||||
|
return `rtk-query-monitor-tab-panel-${value}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderTabPanelButtonId(value: QueryPreviewTabs): string {
|
||||||
|
return renderTabPanelId(value) + '-button';
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export default {};
|
|
@ -0,0 +1,7 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { createDevTools } from '@redux-devtools/core';
|
||||||
|
import { RtkQueryMonitor } from '../src';
|
||||||
|
|
||||||
|
const MonitorAsAny = RtkQueryMonitor as any;
|
||||||
|
|
||||||
|
export const ReduxDevTools = createDevTools(<MonitorAsAny />);
|
|
@ -0,0 +1,119 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||||
|
import { ReduxDevTools } from './devtools.mocks';
|
||||||
|
import { BaseQueryJestMockFunction, setupStore } from './rtk-query.mocks';
|
||||||
|
|
||||||
|
function Providers({
|
||||||
|
store,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
store: ReturnType<typeof setupStore>['store'];
|
||||||
|
children?: React.ComponentProps<typeof Provider>['children'];
|
||||||
|
}) {
|
||||||
|
const AnyProvider = Provider as any;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="app-root">
|
||||||
|
<AnyProvider store={store}>
|
||||||
|
{children}
|
||||||
|
<ReduxDevTools />
|
||||||
|
</AnyProvider>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('rtk-query-monitor standalone integration', () => {
|
||||||
|
// Hushes symbol.observable warning
|
||||||
|
// @see https://github.com/reduxjs/redux-devtools/issues/1002
|
||||||
|
jest.spyOn(console, 'warn');
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
(console.warn as jest.Mock<void>).mockImplementation(() => {});
|
||||||
|
|
||||||
|
const dataPanelDomId = '#rtk-query-monitor-tab-panel-0';
|
||||||
|
|
||||||
|
const childrenTextContent = 'Renders children';
|
||||||
|
const fetchBaseQueryMock: BaseQueryJestMockFunction<Record<string, unknown>> =
|
||||||
|
jest.fn((...fetchArgs) =>
|
||||||
|
Promise.resolve({
|
||||||
|
data: {
|
||||||
|
name: fetchArgs[0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const { store, pokemonApi } = setupStore(fetchBaseQueryMock, ReduxDevTools);
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
// let's populate api
|
||||||
|
(store.dispatch as any)(
|
||||||
|
pokemonApi.endpoints.getPokemonByName.initiate('bulbasaur')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fetchBaseQueryMock.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
(console.warn as jest.Mock<void>).mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders on a standalone app without crashing', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Providers store={store}>
|
||||||
|
<div data-testid="children">{childrenTextContent}</div>
|
||||||
|
</Providers>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByTestId('children').textContent).toBe(
|
||||||
|
childrenTextContent
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen
|
||||||
|
.getByRole('tab', { name: /actions/i })
|
||||||
|
?.textContent?.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
).toBe('actions');
|
||||||
|
expect(
|
||||||
|
screen
|
||||||
|
.getByRole('tab', { name: /data/i })
|
||||||
|
?.textContent?.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
).toBe('data');
|
||||||
|
expect(
|
||||||
|
screen
|
||||||
|
.getByRole('tab', { name: /api/i })
|
||||||
|
?.textContent?.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
).toBe('api');
|
||||||
|
expect(
|
||||||
|
container.querySelector(
|
||||||
|
'form[id="rtk-query-monitor-query-selection-form"]'
|
||||||
|
)
|
||||||
|
).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays query data tab content', async () => {
|
||||||
|
// `Promise.resolve()` hushes `@typescript-eslint/await-thenable`
|
||||||
|
await Promise.resolve(pokemonApi.util.getRunningOperationPromises());
|
||||||
|
|
||||||
|
const { container } = render(
|
||||||
|
<Providers store={store}>
|
||||||
|
<div data-testid="children">{childrenTextContent}</div>
|
||||||
|
</Providers>
|
||||||
|
);
|
||||||
|
|
||||||
|
// We need to select the query & the correct tab
|
||||||
|
fireEvent.click(screen.getByRole('tab', { name: /data/i }));
|
||||||
|
fireEvent.click(screen.getByText(/bulbasaur/i));
|
||||||
|
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(container.querySelector(dataPanelDomId)).not.toBeNull()
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container.querySelector(dataPanelDomId)?.textContent).toMatch(
|
||||||
|
/name\W+pokemon\/bulbasaur/i
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,84 @@
|
||||||
|
import {
|
||||||
|
combineReducers,
|
||||||
|
configureStore,
|
||||||
|
EnhancedStore,
|
||||||
|
Middleware,
|
||||||
|
} from '@reduxjs/toolkit';
|
||||||
|
import { createApi } from '@reduxjs/toolkit/query/react';
|
||||||
|
import type { BaseQueryFn, FetchArgs } from '@reduxjs/toolkit/query';
|
||||||
|
import type { ReduxDevTools } from './devtools.mocks';
|
||||||
|
|
||||||
|
export type MockBaseQuery<
|
||||||
|
Result,
|
||||||
|
Args = string | FetchArgs,
|
||||||
|
Meta = { status?: number }
|
||||||
|
> = BaseQueryFn<Args, Result, unknown, Meta>;
|
||||||
|
|
||||||
|
export type BaseQueryJestMockFunction<Result> = jest.Mock<
|
||||||
|
ReturnType<MockBaseQuery<Result>>,
|
||||||
|
Parameters<MockBaseQuery<Result>>
|
||||||
|
>;
|
||||||
|
|
||||||
|
export function createMockBaseQuery<Result>(
|
||||||
|
jestMockFn: BaseQueryJestMockFunction<Result>
|
||||||
|
): MockBaseQuery<Result> {
|
||||||
|
return async function mockBaseQuery(param, api, extra) {
|
||||||
|
try {
|
||||||
|
const output = await jestMockFn(param, api, extra);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createPokemonApi(
|
||||||
|
jestMockFn: BaseQueryJestMockFunction<Record<string, any>>
|
||||||
|
) {
|
||||||
|
return createApi({
|
||||||
|
reducerPath: 'pokemonApi',
|
||||||
|
keepUnusedDataFor: 9999,
|
||||||
|
baseQuery: createMockBaseQuery(jestMockFn),
|
||||||
|
tagTypes: ['pokemon'],
|
||||||
|
endpoints: (builder) => ({
|
||||||
|
getPokemonByName: builder.query<Record<string, any>, string>({
|
||||||
|
query: (name: string) => `pokemon/${name}`,
|
||||||
|
providesTags: (result, error, name: string) => [
|
||||||
|
{ type: 'pokemon' },
|
||||||
|
{ type: 'pokemon', id: name },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setupStore(
|
||||||
|
jestMockFn: BaseQueryJestMockFunction<Record<string, any>>,
|
||||||
|
devTools: typeof ReduxDevTools
|
||||||
|
) {
|
||||||
|
const pokemonApi = createPokemonApi(jestMockFn);
|
||||||
|
|
||||||
|
const reducer = combineReducers({
|
||||||
|
[pokemonApi.reducerPath]: pokemonApi.reducer,
|
||||||
|
});
|
||||||
|
|
||||||
|
const store: EnhancedStore<ReturnType<typeof reducer>> = configureStore({
|
||||||
|
reducer,
|
||||||
|
devTools: false,
|
||||||
|
// adding the api middleware enables caching, invalidation, polling and other features of `rtk-query`
|
||||||
|
middleware: (getDefaultMiddleware) =>
|
||||||
|
getDefaultMiddleware().concat([pokemonApi.middleware]) as Middleware[],
|
||||||
|
enhancers: [devTools.instrument()],
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
jestMockFn,
|
||||||
|
devTools,
|
||||||
|
store,
|
||||||
|
reducer,
|
||||||
|
pokemonApi,
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.react.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["jest"]
|
||||||
|
},
|
||||||
|
"include": ["src", "test"],
|
||||||
|
"exclude": ["dist"]
|
||||||
|
}
|
|
@ -1788,7 +1788,10 @@ importers:
|
||||||
'@redux-devtools/core': ^3.13.1
|
'@redux-devtools/core': ^3.13.1
|
||||||
'@redux-devtools/ui': ^1.3.0
|
'@redux-devtools/ui': ^1.3.0
|
||||||
'@reduxjs/toolkit': ^1.8.2
|
'@reduxjs/toolkit': ^1.8.2
|
||||||
|
'@testing-library/jest-dom': ^5.16.4
|
||||||
|
'@testing-library/react': ^13.3.0
|
||||||
'@types/hex-rgba': ^1.0.1
|
'@types/hex-rgba': ^1.0.1
|
||||||
|
'@types/jest': ^27.5.2
|
||||||
'@types/lodash': ^4.14.182
|
'@types/lodash': ^4.14.182
|
||||||
'@types/lodash.debounce': ^4.0.7
|
'@types/lodash.debounce': ^4.0.7
|
||||||
'@types/prop-types': ^15.7.5
|
'@types/prop-types': ^15.7.5
|
||||||
|
@ -1798,20 +1801,25 @@ importers:
|
||||||
'@typescript-eslint/parser': ^5.29.0
|
'@typescript-eslint/parser': ^5.29.0
|
||||||
eslint: ^8.18.0
|
eslint: ^8.18.0
|
||||||
eslint-config-prettier: ^8.5.0
|
eslint-config-prettier: ^8.5.0
|
||||||
|
eslint-plugin-jest: ^26.5.3
|
||||||
eslint-plugin-react: ^7.30.1
|
eslint-plugin-react: ^7.30.1
|
||||||
eslint-plugin-react-hooks: ^4.6.0
|
eslint-plugin-react-hooks: ^4.6.0
|
||||||
hex-rgba: ^1.0.2
|
hex-rgba: ^1.0.2
|
||||||
immutable: ^4.1.0
|
immutable: ^4.1.0
|
||||||
|
jest: ^27.5.1
|
||||||
jss: ^10.9.0
|
jss: ^10.9.0
|
||||||
jss-preset-default: ^10.9.0
|
jss-preset-default: ^10.9.0
|
||||||
lodash.debounce: ^4.0.8
|
lodash.debounce: ^4.0.8
|
||||||
prop-types: ^15.8.1
|
prop-types: ^15.8.1
|
||||||
react: ^18.2.0
|
react: ^18.2.0
|
||||||
react-base16-styling: ^0.9.1
|
react-base16-styling: ^0.9.1
|
||||||
|
react-dom: ^18.2.0
|
||||||
react-json-tree: ^0.17.0
|
react-json-tree: ^0.17.0
|
||||||
|
react-redux: ^8.0.2
|
||||||
redux: ^4.2.0
|
redux: ^4.2.0
|
||||||
redux-devtools-themes: ^1.0.0
|
redux-devtools-themes: ^1.0.0
|
||||||
rimraf: ^3.0.2
|
rimraf: ^3.0.2
|
||||||
|
ts-jest: ^27.1.5
|
||||||
typescript: ~4.7.4
|
typescript: ~4.7.4
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.18.3
|
'@babel/runtime': 7.18.3
|
||||||
|
@ -1837,19 +1845,27 @@ importers:
|
||||||
'@babel/preset-react': 7.17.12_@babel+core@7.18.5
|
'@babel/preset-react': 7.17.12_@babel+core@7.18.5
|
||||||
'@babel/preset-typescript': 7.17.12_@babel+core@7.18.5
|
'@babel/preset-typescript': 7.17.12_@babel+core@7.18.5
|
||||||
'@redux-devtools/core': link:../redux-devtools
|
'@redux-devtools/core': link:../redux-devtools
|
||||||
'@reduxjs/toolkit': 1.8.2_react@18.2.0
|
'@reduxjs/toolkit': 1.8.2_kkwg4cbsojnjnupd3btipussee
|
||||||
|
'@testing-library/jest-dom': 5.16.4
|
||||||
|
'@testing-library/react': 13.3.0_biqbaboplfbrettd7655fr4n2y
|
||||||
'@types/hex-rgba': 1.0.1
|
'@types/hex-rgba': 1.0.1
|
||||||
|
'@types/jest': 27.5.2
|
||||||
'@types/lodash.debounce': 4.0.7
|
'@types/lodash.debounce': 4.0.7
|
||||||
'@types/react': 18.0.14
|
'@types/react': 18.0.14
|
||||||
'@typescript-eslint/eslint-plugin': 5.29.0_qqmbkyiaixvppdwswpytuf2hgm
|
'@typescript-eslint/eslint-plugin': 5.29.0_qqmbkyiaixvppdwswpytuf2hgm
|
||||||
'@typescript-eslint/parser': 5.29.0_b5e7v2qnwxfo6hmiq56u52mz3e
|
'@typescript-eslint/parser': 5.29.0_b5e7v2qnwxfo6hmiq56u52mz3e
|
||||||
eslint: 8.18.0
|
eslint: 8.18.0
|
||||||
eslint-config-prettier: 8.5.0_eslint@8.18.0
|
eslint-config-prettier: 8.5.0_eslint@8.18.0
|
||||||
|
eslint-plugin-jest: 26.5.3_hkaktba3mic4t6mktu5mmyzyhi
|
||||||
eslint-plugin-react: 7.30.1_eslint@8.18.0
|
eslint-plugin-react: 7.30.1_eslint@8.18.0
|
||||||
eslint-plugin-react-hooks: 4.6.0_eslint@8.18.0
|
eslint-plugin-react-hooks: 4.6.0_eslint@8.18.0
|
||||||
|
jest: 27.5.1
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0_react@18.2.0
|
||||||
|
react-redux: 8.0.2_42iqcqzqjdyq32nxzztmetzyhu
|
||||||
redux: 4.2.0
|
redux: 4.2.0
|
||||||
rimraf: 3.0.2
|
rimraf: 3.0.2
|
||||||
|
ts-jest: 27.1.5_7giygfzd3xe4pjz4ngu3nwlqbm
|
||||||
typescript: 4.7.4
|
typescript: 4.7.4
|
||||||
|
|
||||||
packages/redux-devtools-rtk-query-monitor/demo:
|
packages/redux-devtools-rtk-query-monitor/demo:
|
||||||
|
@ -1886,7 +1902,7 @@ importers:
|
||||||
fork-ts-checker-webpack-plugin: ^7.2.11
|
fork-ts-checker-webpack-plugin: ^7.2.11
|
||||||
framer-motion: ^6.3.15
|
framer-motion: ^6.3.15
|
||||||
html-webpack-plugin: ^5.5.0
|
html-webpack-plugin: ^5.5.0
|
||||||
msw: ^0.42.3
|
msw: ^0.43.0
|
||||||
react: ^18.2.0
|
react: ^18.2.0
|
||||||
react-dom: ^18.2.0
|
react-dom: ^18.2.0
|
||||||
react-icons: ^4.4.0
|
react-icons: ^4.4.0
|
||||||
|
@ -1911,7 +1927,7 @@ importers:
|
||||||
'@redux-devtools/rtk-query-monitor': link:..
|
'@redux-devtools/rtk-query-monitor': link:..
|
||||||
'@reduxjs/toolkit': 1.8.2_kkwg4cbsojnjnupd3btipussee
|
'@reduxjs/toolkit': 1.8.2_kkwg4cbsojnjnupd3btipussee
|
||||||
framer-motion: 6.3.15_biqbaboplfbrettd7655fr4n2y
|
framer-motion: 6.3.15_biqbaboplfbrettd7655fr4n2y
|
||||||
msw: 0.42.3_typescript@4.7.4
|
msw: 0.43.0_typescript@4.7.4
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0_react@18.2.0
|
react-dom: 18.2.0_react@18.2.0
|
||||||
react-icons: 4.4.0_react@18.2.0
|
react-icons: 4.4.0_react@18.2.0
|
||||||
|
@ -5999,29 +6015,10 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
immer: 9.0.15
|
immer: 9.0.15
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-redux: 8.0.2_fzknh3pugl53jp7xsetxkg5ani
|
react-redux: 8.0.2_42iqcqzqjdyq32nxzztmetzyhu
|
||||||
redux: 4.2.0
|
redux: 4.2.0
|
||||||
redux-thunk: 2.4.1_redux@4.2.0
|
redux-thunk: 2.4.1_redux@4.2.0
|
||||||
reselect: 4.1.6
|
reselect: 4.1.6
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@reduxjs/toolkit/1.8.2_react@18.2.0:
|
|
||||||
resolution: {integrity: sha512-CtPw5TkN1pHRigMFCOS/0qg3b/yfPV5qGCsltVnIz7bx4PKTJlGHYfIxm97qskLknMzuGfjExaYdXJ77QTL0vg==}
|
|
||||||
peerDependencies:
|
|
||||||
react: ^16.9.0 || ^17.0.0 || ^18 || 18
|
|
||||||
react-redux: ^7.2.1 || ^8.0.0-beta
|
|
||||||
peerDependenciesMeta:
|
|
||||||
react:
|
|
||||||
optional: true
|
|
||||||
react-redux:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
immer: 9.0.15
|
|
||||||
react: 18.2.0
|
|
||||||
redux: 4.2.0
|
|
||||||
redux-thunk: 2.4.1_redux@4.2.0
|
|
||||||
reselect: 4.1.6
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@restart/hooks/0.4.7_react@18.2.0:
|
/@restart/hooks/0.4.7_react@18.2.0:
|
||||||
resolution: {integrity: sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A==}
|
resolution: {integrity: sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A==}
|
||||||
|
@ -16403,43 +16400,6 @@ packages:
|
||||||
/ms/2.1.3:
|
/ms/2.1.3:
|
||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||||
|
|
||||||
/msw/0.42.3_typescript@4.7.4:
|
|
||||||
resolution: {integrity: sha512-zrKBIGCDsNUCZLd3DLSeUtRruZ0riwJgORg9/bSDw3D0PTI8XUGAK3nC0LJA9g0rChGuKaWK/SwObA8wpFrz4g==}
|
|
||||||
engines: {node: '>=14'}
|
|
||||||
hasBin: true
|
|
||||||
requiresBuild: true
|
|
||||||
peerDependencies:
|
|
||||||
typescript: '>= 4.2.x <= 4.7.x'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
typescript:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@mswjs/cookies': 0.2.1
|
|
||||||
'@mswjs/interceptors': 0.16.6
|
|
||||||
'@open-draft/until': 1.0.3
|
|
||||||
'@types/cookie': 0.4.1
|
|
||||||
'@types/js-levenshtein': 1.1.1
|
|
||||||
chalk: 4.1.1
|
|
||||||
chokidar: 3.5.3
|
|
||||||
cookie: 0.4.2
|
|
||||||
graphql: 16.5.0
|
|
||||||
headers-polyfill: 3.0.7
|
|
||||||
inquirer: 8.2.4
|
|
||||||
is-node-process: 1.0.1
|
|
||||||
js-levenshtein: 1.1.6
|
|
||||||
node-fetch: 2.6.7
|
|
||||||
outvariant: 1.3.0
|
|
||||||
path-to-regexp: 6.2.1
|
|
||||||
statuses: 2.0.1
|
|
||||||
strict-event-emitter: 0.2.4
|
|
||||||
type-fest: 1.4.0
|
|
||||||
typescript: 4.7.4
|
|
||||||
yargs: 17.5.1
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- encoding
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/msw/0.43.0_typescript@4.7.4:
|
/msw/0.43.0_typescript@4.7.4:
|
||||||
resolution: {integrity: sha512-XJylZP0qW3D5WUGWh9FFefJEl3MGG4y1I+/8a833d0eedm6B+GaPm6wPVZNcnlS2YVTagvEgShVJ7ZtY66tTRQ==}
|
resolution: {integrity: sha512-XJylZP0qW3D5WUGWh9FFefJEl3MGG4y1I+/8a833d0eedm6B+GaPm6wPVZNcnlS2YVTagvEgShVJ7ZtY66tTRQ==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
@ -16476,7 +16436,6 @@ packages:
|
||||||
- encoding
|
- encoding
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
|
||||||
/multicast-dns/7.2.5:
|
/multicast-dns/7.2.5:
|
||||||
resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==}
|
resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==}
|
||||||
|
@ -18192,7 +18151,6 @@ packages:
|
||||||
react-is: 18.2.0
|
react-is: 18.2.0
|
||||||
redux: 4.2.0
|
redux: 4.2.0
|
||||||
use-sync-external-store: 1.2.0_react@18.2.0
|
use-sync-external-store: 1.2.0_react@18.2.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/react-redux/8.0.2_fzknh3pugl53jp7xsetxkg5ani:
|
/react-redux/8.0.2_fzknh3pugl53jp7xsetxkg5ani:
|
||||||
resolution: {integrity: sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==}
|
resolution: {integrity: sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user