mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-06-08 23:23:07 +03:00
Merge branch 'main' into state-filter
This commit is contained in:
commit
e1cd49dcc8
|
@ -1,5 +1,19 @@
|
||||||
# remotedev-redux-devtools-extension
|
# remotedev-redux-devtools-extension
|
||||||
|
|
||||||
|
## 3.0.19
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 450cde6e: Fix responsive layout
|
||||||
|
|
||||||
|
## 3.0.18
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [81926f32]
|
||||||
|
- react-json-tree@0.18.0
|
||||||
|
- @redux-devtools/app@2.2.1
|
||||||
|
|
||||||
## 3.0.17
|
## 3.0.17
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "3.0.17",
|
"version": "3.0.19",
|
||||||
"name": "Redux DevTools",
|
"name": "Redux DevTools",
|
||||||
"description": "Redux DevTools for debugging application's state changes.",
|
"description": "Redux DevTools for debugging application's state changes.",
|
||||||
"homepage_url": "https://github.com/reduxjs/redux-devtools",
|
"homepage_url": "https://github.com/reduxjs/redux-devtools",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "3.0.17",
|
"version": "3.0.19",
|
||||||
"name": "Redux DevTools",
|
"name": "Redux DevTools",
|
||||||
"description": "Redux DevTools for debugging application's state changes.",
|
"description": "Redux DevTools for debugging application's state changes.",
|
||||||
"homepage_url": "https://github.com/reduxjs/redux-devtools",
|
"homepage_url": "https://github.com/reduxjs/redux-devtools",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "3.0.17",
|
"version": "3.0.19",
|
||||||
"name": "Redux DevTools",
|
"name": "Redux DevTools",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"description": "Redux Developer Tools for debugging application state changes.",
|
"description": "Redux Developer Tools for debugging application state changes.",
|
||||||
|
|
|
@ -5,5 +5,7 @@ module.exports = {
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'\\.css$': '<rootDir>/test/__mocks__/styleMock.ts',
|
'\\.css$': '<rootDir>/test/__mocks__/styleMock.ts',
|
||||||
},
|
},
|
||||||
resolver: '<rootDir>/jestResolver.js',
|
transformIgnorePatterns: [
|
||||||
|
'node_modules/(?!.pnpm|d3|dateformat|delaunator|internmap|nanoid|robust-predicates|uuid)',
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
module.exports = (path, options) => {
|
|
||||||
return options.defaultResolver(path, {
|
|
||||||
...options,
|
|
||||||
packageFilter: (pkg) => {
|
|
||||||
if (pkg.name === 'nanoid') {
|
|
||||||
pkg.exports['.'].browser = pkg.exports['.'].require;
|
|
||||||
}
|
|
||||||
if (pkg.name === 'uuid' && pkg.version.startsWith('8.')) {
|
|
||||||
delete pkg.exports;
|
|
||||||
delete pkg.module;
|
|
||||||
}
|
|
||||||
return pkg;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "remotedev-redux-devtools-extension",
|
"name": "remotedev-redux-devtools-extension",
|
||||||
"version": "3.0.17",
|
"version": "3.0.19",
|
||||||
"description": "Redux Developer Tools for debugging application state changes.",
|
"description": "Redux Developer Tools for debugging application state changes.",
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/extension",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/extension",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.12.1",
|
||||||
"@redux-devtools/app": "^2.2.0",
|
"@redux-devtools/app": "^2.2.1",
|
||||||
"@redux-devtools/core": "^3.13.0",
|
"@redux-devtools/core": "^3.13.0",
|
||||||
"@redux-devtools/instrument": "^2.1.0",
|
"@redux-devtools/instrument": "^2.1.0",
|
||||||
"@redux-devtools/serialize": "^0.4.1",
|
"@redux-devtools/serialize": "^0.4.1",
|
||||||
|
@ -43,53 +43,53 @@
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^4.7.1",
|
"react-icons": "^4.7.1",
|
||||||
"react-is": "^18.2.0",
|
"react-is": "^18.2.0",
|
||||||
"react-json-tree": "^0.17.0",
|
"react-json-tree": "^0.18.0",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.0.5",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"styled-components": "^5.3.6"
|
"styled-components": "^5.3.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@babel/register": "^7.18.9",
|
"@babel/register": "^7.21.0",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@types/chrome": "^0.0.206",
|
"@types/chrome": "^0.0.218",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
"babel-loader": "^9.1.0",
|
"babel-loader": "^9.1.2",
|
||||||
"chromedriver": "^108.0.0",
|
"chromedriver": "^110.0.0",
|
||||||
"copy-webpack-plugin": "^11.0.0",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"cpy-cli": "^4.2.0",
|
"cpy-cli": "^4.2.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.7.3",
|
||||||
"electron": "^22.0.0",
|
"electron": "^23.1.1",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"eslint-plugin-jsx-a11y": "^6.6.1",
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.14",
|
"fork-ts-checker-webpack-plugin": "^8.0.0",
|
||||||
"immutable": "^4.1.0",
|
"immutable": "^4.2.4",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.3",
|
||||||
"jest-environment-jsdom": "^29.3.1",
|
"jest-environment-jsdom": "^29.4.3",
|
||||||
"pug-html-loader": "^1.1.5",
|
"pug-html-loader": "^1.1.5",
|
||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"react-transform-catch-errors": "^1.0.2",
|
"react-transform-catch-errors": "^1.0.2",
|
||||||
"react-transform-hmr": "^1.0.4",
|
"react-transform-hmr": "^1.0.4",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"selenium-webdriver": "^4.7.1",
|
"selenium-webdriver": "^4.8.1",
|
||||||
"sinon-chrome": "^3.0.1",
|
"sinon-chrome": "^3.0.1",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"ts-jest": "^29.0.3",
|
"ts-jest": "^29.0.5",
|
||||||
"typescript": "~4.9.4",
|
"typescript": "~4.9.5",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-cli": "^5.0.1"
|
"webpack-cli": "^5.0.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -591,12 +591,25 @@ const preEnhancer =
|
||||||
} as any;
|
} as any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type InferComposedStoreExt<StoreEnhancers> = StoreEnhancers extends [
|
||||||
|
infer HeadStoreEnhancer,
|
||||||
|
...infer RestStoreEnhancers
|
||||||
|
]
|
||||||
|
? HeadStoreEnhancer extends StoreEnhancer<infer StoreExt>
|
||||||
|
? StoreExt & InferComposedStoreExt<RestStoreEnhancers>
|
||||||
|
: never
|
||||||
|
: unknown;
|
||||||
|
|
||||||
const extensionCompose =
|
const extensionCompose =
|
||||||
(config: Config) =>
|
(config: Config) =>
|
||||||
(...funcs: StoreEnhancer[]): StoreEnhancer => {
|
<StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
|
...funcs: StoreEnhancers
|
||||||
|
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>> => {
|
||||||
|
// @ts-ignore FIXME
|
||||||
return (...args) => {
|
return (...args) => {
|
||||||
const instanceId = generateId(config.instanceId);
|
const instanceId = generateId(config.instanceId);
|
||||||
return [preEnhancer(instanceId), ...funcs].reduceRight(
|
return [preEnhancer(instanceId), ...funcs].reduceRight(
|
||||||
|
// @ts-ignore FIXME
|
||||||
(composed, f) => f(composed),
|
(composed, f) => f(composed),
|
||||||
__REDUX_DEVTOOLS_EXTENSION__({ ...config, instanceId })(...args)
|
__REDUX_DEVTOOLS_EXTENSION__({ ...config, instanceId })(...args)
|
||||||
);
|
);
|
||||||
|
@ -604,8 +617,12 @@ const extensionCompose =
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ReduxDevtoolsExtensionCompose {
|
interface ReduxDevtoolsExtensionCompose {
|
||||||
(config: Config): (...funcs: StoreEnhancer[]) => StoreEnhancer;
|
(config: Config): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
(...funcs: StoreEnhancer[]): StoreEnhancer;
|
...funcs: StoreEnhancers
|
||||||
|
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
<StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
|
...funcs: StoreEnhancers
|
||||||
|
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -616,18 +633,24 @@ declare global {
|
||||||
|
|
||||||
function reduxDevtoolsExtensionCompose(
|
function reduxDevtoolsExtensionCompose(
|
||||||
config: Config
|
config: Config
|
||||||
): (...funcs: StoreEnhancer[]) => StoreEnhancer;
|
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
|
...funcs: StoreEnhancers
|
||||||
|
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
function reduxDevtoolsExtensionCompose<
|
||||||
|
StoreEnhancers extends readonly StoreEnhancer<unknown>[]
|
||||||
|
>(
|
||||||
|
...funcs: StoreEnhancers
|
||||||
|
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
function reduxDevtoolsExtensionCompose(
|
function reduxDevtoolsExtensionCompose(
|
||||||
...funcs: StoreEnhancer[]
|
...funcs: [Config] | StoreEnhancer<unknown>[]
|
||||||
): StoreEnhancer;
|
) {
|
||||||
function reduxDevtoolsExtensionCompose(...funcs: [Config] | StoreEnhancer[]) {
|
|
||||||
if (funcs.length === 0) {
|
if (funcs.length === 0) {
|
||||||
return __REDUX_DEVTOOLS_EXTENSION__();
|
return __REDUX_DEVTOOLS_EXTENSION__();
|
||||||
}
|
}
|
||||||
if (funcs.length === 1 && typeof funcs[0] === 'object') {
|
if (funcs.length === 1 && typeof funcs[0] === 'object') {
|
||||||
return extensionCompose(funcs[0]);
|
return extensionCompose(funcs[0]);
|
||||||
}
|
}
|
||||||
return extensionCompose({})(...(funcs as StoreEnhancer[]));
|
return extensionCompose({})(...(funcs as StoreEnhancer<unknown>[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ = reduxDevtoolsExtensionCompose;
|
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ = reduxDevtoolsExtensionCompose;
|
||||||
|
|
|
@ -7,7 +7,7 @@ style.
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 760px;
|
min-width: 350px;
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -17,7 +17,6 @@ style.
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
#root {
|
#root {
|
||||||
min-width: 760px;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
#root > div {
|
#root > div {
|
||||||
|
|
26
package.json
26
package.json
|
@ -1,21 +1,21 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@changesets/cli": "^2.26.0",
|
"@changesets/cli": "^2.26.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-jest": "^27.1.7",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.3",
|
||||||
"prettier": "2.8.1",
|
"prettier": "2.8.4",
|
||||||
"typescript": "~4.9.4",
|
"typescript": "~4.9.5",
|
||||||
"nx": "^15.3.3",
|
"nx": "^15.8.1",
|
||||||
"@nrwl/nx-cloud": "^15.0.2"
|
"@nrwl/nx-cloud": "^15.1.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
"packages/redux-devtools-rtk-query-monitor/demo",
|
"packages/redux-devtools-rtk-query-monitor/demo",
|
||||||
"packages/redux-devtools-slider-monitor/examples/todomvc"
|
"packages/redux-devtools-slider-monitor/examples/todomvc"
|
||||||
],
|
],
|
||||||
"packageManager": "pnpm@7.19.0",
|
"packageManager": "pnpm@7.28.0",
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@babel/highlight>chalk": "Methuselah96/chalk#v2-without-process"
|
"@babel/highlight>chalk": "Methuselah96/chalk#v2-without-process"
|
||||||
|
|
|
@ -1,5 +1,23 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 2.0.0
|
||||||
|
|
||||||
|
### Major Changes
|
||||||
|
|
||||||
|
- b323f77d: Upgrade D3
|
||||||
|
|
||||||
|
- Remove UMD build.
|
||||||
|
- Split `style` option into `chartStyles`, `nodeStyleOptions`, `textStyleOptions`, and `linkStyles`.
|
||||||
|
- The shape of the argument passed to the `onClickText` option has been updated.
|
||||||
|
- Rename `InputOptions` to `Options`, `Primitive` to `StyleValue`, and `NodeWithId` to `HierarchyPointNode<Node>`.
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [b323f77d]
|
||||||
|
- Updated dependencies [b323f77d]
|
||||||
|
- d3tooltip@3.0.0
|
||||||
|
- map2tree@3.0.0
|
||||||
|
|
||||||
## [1.4.0](https://github.com/reduxjs/redux-devtools/compare/d3-state-visualizer@1.3.4...d3-state-visualizer@1.4.0) (2021-03-06)
|
## [1.4.0](https://github.com/reduxjs/redux-devtools/compare/d3-state-visualizer@1.3.4...d3-state-visualizer@1.4.0) (2021-03-06)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
|
@ -35,7 +35,7 @@ const render = tree(document.getElementById('root'), {
|
||||||
isSorted: false,
|
isSorted: false,
|
||||||
widthBetweenNodesCoeff: 1.5,
|
widthBetweenNodesCoeff: 1.5,
|
||||||
heightBetweenNodesCoeff: 2,
|
heightBetweenNodesCoeff: 2,
|
||||||
style: { border: '1px solid black' },
|
chartStyles: { border: '1px solid black' },
|
||||||
tooltipOptions: { offset: { left: 30, top: 10 }, indentationSize: 2 },
|
tooltipOptions: { offset: { left: 30, top: 10 }, indentationSize: 2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ Other options are listed below and have reasonable default values if you want to
|
||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
| ------------------------- | ------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------- | ------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `id` | String | `'d3svg'` | Sets the identifier of the SVG element —i.e your chart— that will be added to the DOM element you passed as first argument |
|
| `id` | String | `'d3svg'` | Sets the identifier of the SVG element —i.e your chart— that will be added to the DOM element you passed as first argument |
|
||||||
| `style` | Object | `{}` | Sets the CSS style of the chart |
|
| `chartStyles` | Object | `{}` | Sets the CSS style of the chart |
|
||||||
| `size` | Number | `500` | Sets size of the chart in pixels |
|
| `size` | Number | `500` | Sets size of the chart in pixels |
|
||||||
| `aspectRatio` | Float | `1.0` | Sets the chart height to `size * aspectRatio` and [viewBox](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox) in order to preserve the aspect ratio of the chart. [Great video](https://www.youtube.com/watch?v=FCOeMy7HrBc) if you want to learn more about how SVG works |
|
| `aspectRatio` | Float | `1.0` | Sets the chart height to `size * aspectRatio` and [viewBox](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox) in order to preserve the aspect ratio of the chart. [Great video](https://www.youtube.com/watch?v=FCOeMy7HrBc) if you want to learn more about how SVG works |
|
||||||
| `widthBetweenNodesCoeff` | Float | `1.0` | Alters the horizontal space between each node |
|
| `widthBetweenNodesCoeff` | Float | `1.0` | Alters the horizontal space between each node |
|
||||||
|
@ -74,12 +74,6 @@ Other options are listed below and have reasonable default values if you want to
|
||||||
|
|
||||||
More to come...
|
More to come...
|
||||||
|
|
||||||
## Bindings
|
|
||||||
|
|
||||||
### React
|
|
||||||
|
|
||||||
[example](https://github.com/reduxjs/redux-devtools/tree/master/packages/d3-state-visualizer/examples/react-tree) implementation.
|
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
- Threshold for large arrays so only a single node is displayed instead of all the children. That single node would be exclude from searching until selected.
|
- Threshold for large arrays so only a single node is displayed instead of all the children. That single node would be exclude from searching until selected.
|
||||||
|
|
10
packages/d3-state-visualizer/examples/tree/CHANGELOG.md
Normal file
10
packages/d3-state-visualizer/examples/tree/CHANGELOG.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# d3-state-visualizer-tree-example
|
||||||
|
|
||||||
|
## 0.1.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [b323f77d]
|
||||||
|
- Updated dependencies [b323f77d]
|
||||||
|
- d3-state-visualizer@2.0.0
|
||||||
|
- map2tree@3.0.0
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "d3-state-visualizer-tree-example",
|
"name": "d3-state-visualizer-tree-example",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"description": "Visualize your app state as a tree",
|
"description": "Visualize your app state as a tree",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"d3",
|
"d3",
|
||||||
|
@ -25,24 +25,24 @@
|
||||||
"type-check": "tsc --noEmit"
|
"type-check": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3-state-visualizer": "^1.6.0",
|
"d3-state-visualizer": "^2.0.0",
|
||||||
"map2tree": "^2.1.0"
|
"map2tree": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.14.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"babel-loader": "^9.1.0",
|
"babel-loader": "^9.1.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.14",
|
"fork-ts-checker-webpack-plugin": "^8.0.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "~4.9.4",
|
"typescript": "~4.9.5",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-cli": "^5.0.1",
|
"webpack-cli": "^5.0.1",
|
||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.11.1"
|
||||||
|
|
|
@ -28,7 +28,7 @@ const render = tree(document.getElementById('root')!, {
|
||||||
isSorted: false,
|
isSorted: false,
|
||||||
widthBetweenNodesCoeff: 1.5,
|
widthBetweenNodesCoeff: 1.5,
|
||||||
heightBetweenNodesCoeff: 2,
|
heightBetweenNodesCoeff: 2,
|
||||||
style: { border: '1px solid black' },
|
chartStyles: { border: '1px solid black' },
|
||||||
tooltipOptions: { offset: { left: 30, top: 10 }, indentationSize: 2 },
|
tooltipOptions: { offset: { left: 30, top: 10 }, indentationSize: 2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "d3-state-visualizer",
|
"name": "d3-state-visualizer",
|
||||||
"version": "1.6.0",
|
"version": "2.0.0",
|
||||||
"description": "Visualize your app state with a range of reusable charts",
|
"description": "Visualize your app state with a range of reusable charts",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"d3",
|
"d3",
|
||||||
|
@ -23,18 +23,16 @@
|
||||||
"main": "lib/cjs/index.js",
|
"main": "lib/cjs/index.js",
|
||||||
"module": "lib/esm/index.js",
|
"module": "lib/esm/index.js",
|
||||||
"types": "lib/types/index.d.ts",
|
"types": "lib/types/index.d.ts",
|
||||||
"unpkg": "dist/d3-state-visualizer.umd.js",
|
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm run build:cjs && pnpm run build:esm && pnpm run build:types && pnpm run build:umd",
|
"build": "pnpm run build:cjs && pnpm run build:esm && pnpm run build:types",
|
||||||
"build:cjs": "babel src --extensions \".ts\" --out-dir lib/cjs",
|
"build:cjs": "babel src --extensions \".ts\" --out-dir lib/cjs",
|
||||||
"build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts\" --out-dir lib/esm",
|
"build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts\" --out-dir lib/esm",
|
||||||
"build:types": "tsc --emitDeclarationOnly",
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
"build:umd": "rollup -c",
|
|
||||||
"clean": "rimraf lib",
|
"clean": "rimraf lib",
|
||||||
"lint": "eslint . --ext .ts",
|
"lint": "eslint . --ext .ts",
|
||||||
"type-check": "tsc --noEmit",
|
"type-check": "tsc --noEmit",
|
||||||
|
@ -42,35 +40,26 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint"
|
"prepublish": "pnpm run type-check && pnpm run lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@types/d3": "^3.5.47",
|
"@types/d3": "^7.4.0",
|
||||||
"d3": "^3.5.17",
|
"d3": "^7.8.2",
|
||||||
"d3tooltip": "^2.1.0",
|
"d3tooltip": "^3.0.0",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.3.0",
|
||||||
"map2tree": "^2.1.0",
|
"map2tree": "^3.0.0",
|
||||||
"ramda": "^0.28.0"
|
"ramda": "^0.28.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@rollup/plugin-babel": "^6.0.3",
|
"@types/ramda": "^0.28.23",
|
||||||
"@rollup/plugin-commonjs": "^24.0.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"@rollup/plugin-terser": "^0.2.1",
|
"eslint": "^8.35.0",
|
||||||
"@types/node": "^18.11.17",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"@types/ramda": "^0.28.20",
|
"rimraf": "^4.1.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"typescript": "~4.9.5"
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
|
||||||
"eslint": "^8.30.0",
|
|
||||||
"eslint-config-prettier": "^8.5.0",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"rollup": "^3.7.5",
|
|
||||||
"rollup-plugin-typescript2": "^0.34.1",
|
|
||||||
"tslib": "^2.4.1",
|
|
||||||
"typescript": "~4.9.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
import typescript from 'rollup-plugin-typescript2';
|
|
||||||
import resolve from '@rollup/plugin-node-resolve';
|
|
||||||
import commonjs from '@rollup/plugin-commonjs';
|
|
||||||
import babel from '@rollup/plugin-babel';
|
|
||||||
import terser from '@rollup/plugin-terser';
|
|
||||||
|
|
||||||
const config = [
|
|
||||||
{
|
|
||||||
input: 'src/index.ts',
|
|
||||||
output: {
|
|
||||||
name: 'd3-state-visualizer',
|
|
||||||
file: 'lib/umd/d3-state-visualizer.js',
|
|
||||||
format: 'umd',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript({
|
|
||||||
tsconfigOverride: { compilerOptions: { declaration: false } },
|
|
||||||
}),
|
|
||||||
resolve(),
|
|
||||||
commonjs(),
|
|
||||||
babel({
|
|
||||||
babelHelpers: 'runtime',
|
|
||||||
extensions: ['.ts'],
|
|
||||||
plugins: ['@babel/plugin-transform-runtime'],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/index.ts',
|
|
||||||
output: {
|
|
||||||
name: 'd3-state-visualizer',
|
|
||||||
file: 'lib/umd/d3-state-visualizer.min.js',
|
|
||||||
format: 'umd',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript({
|
|
||||||
tsconfigOverride: { compilerOptions: { declaration: false } },
|
|
||||||
}),
|
|
||||||
resolve(),
|
|
||||||
commonjs(),
|
|
||||||
babel({
|
|
||||||
babelHelpers: 'runtime',
|
|
||||||
extensions: ['.ts'],
|
|
||||||
plugins: ['@babel/plugin-transform-runtime'],
|
|
||||||
}),
|
|
||||||
terser(),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default config;
|
|
|
@ -1,2 +1,4 @@
|
||||||
|
export type { HierarchyPointNode } from 'd3';
|
||||||
|
export type { StyleValue } from 'd3tooltip';
|
||||||
export { default as tree } from './tree/tree';
|
export { default as tree } from './tree/tree';
|
||||||
export type { InputOptions, NodeWithId, Primitive } from './tree/tree';
|
export type { Node, Options } from './tree/tree';
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import d3, { ZoomEvent, Primitive } from 'd3';
|
import * as d3 from 'd3';
|
||||||
|
import type { D3ZoomEvent, HierarchyPointLink, HierarchyPointNode } from 'd3';
|
||||||
import { isEmpty } from 'ramda';
|
import { isEmpty } from 'ramda';
|
||||||
import { map2tree } from 'map2tree';
|
import { map2tree } from 'map2tree';
|
||||||
|
import type { Node } from 'map2tree';
|
||||||
import deepmerge from 'deepmerge';
|
import deepmerge from 'deepmerge';
|
||||||
import {
|
import {
|
||||||
getTooltipString,
|
getTooltipString,
|
||||||
|
@ -9,17 +11,33 @@ import {
|
||||||
getNodeGroupByDepthCount,
|
getNodeGroupByDepthCount,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { tooltip } from 'd3tooltip';
|
import { tooltip } from 'd3tooltip';
|
||||||
|
import type { StyleValue } from 'd3tooltip';
|
||||||
|
|
||||||
export interface InputOptions {
|
export interface Options {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
state?: {} | null;
|
state?: {} | null;
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
tree?: NodeWithId | {};
|
tree?: Node | {};
|
||||||
|
|
||||||
rootKeyName: string;
|
rootKeyName: string;
|
||||||
pushMethod: 'push' | 'unshift';
|
pushMethod: 'push' | 'unshift';
|
||||||
id: string;
|
id: string;
|
||||||
style: { [key: string]: Primitive };
|
chartStyles: { [key: string]: StyleValue };
|
||||||
|
nodeStyleOptions: {
|
||||||
|
colors: {
|
||||||
|
default: string;
|
||||||
|
collapsed: string;
|
||||||
|
parent: string;
|
||||||
|
};
|
||||||
|
radius: number;
|
||||||
|
};
|
||||||
|
textStyleOptions: {
|
||||||
|
colors: {
|
||||||
|
default: string;
|
||||||
|
hover: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
linkStyles: { [key: string]: StyleValue };
|
||||||
size: number;
|
size: number;
|
||||||
aspectRatio: number;
|
aspectRatio: number;
|
||||||
initialZoom: number;
|
initialZoom: number;
|
||||||
|
@ -34,7 +52,7 @@ export interface InputOptions {
|
||||||
widthBetweenNodesCoeff: number;
|
widthBetweenNodesCoeff: number;
|
||||||
transitionDuration: number;
|
transitionDuration: number;
|
||||||
blinkDuration: number;
|
blinkDuration: number;
|
||||||
onClickText: (datum: NodeWithId) => void;
|
onClickText: (datum: HierarchyPointNode<Node>) => void;
|
||||||
tooltipOptions: {
|
tooltipOptions: {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
left?: number | undefined;
|
left?: number | undefined;
|
||||||
|
@ -43,64 +61,7 @@ export interface InputOptions {
|
||||||
left: number;
|
left: number;
|
||||||
top: number;
|
top: number;
|
||||||
};
|
};
|
||||||
style?: { [key: string]: Primitive } | undefined;
|
styles?: { [key: string]: StyleValue } | undefined;
|
||||||
indentationSize?: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Options {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
||||||
state?: {} | null;
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
||||||
tree?: NodeWithId | {};
|
|
||||||
|
|
||||||
rootKeyName: string;
|
|
||||||
pushMethod: 'push' | 'unshift';
|
|
||||||
id: string;
|
|
||||||
style: {
|
|
||||||
node: {
|
|
||||||
colors: {
|
|
||||||
default: string;
|
|
||||||
collapsed: string;
|
|
||||||
parent: string;
|
|
||||||
};
|
|
||||||
radius: number;
|
|
||||||
};
|
|
||||||
text: {
|
|
||||||
colors: {
|
|
||||||
default: string;
|
|
||||||
hover: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
link: {
|
|
||||||
stroke: string;
|
|
||||||
fill: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
size: number;
|
|
||||||
aspectRatio: number;
|
|
||||||
initialZoom: number;
|
|
||||||
margin: {
|
|
||||||
top: number;
|
|
||||||
right: number;
|
|
||||||
bottom: number;
|
|
||||||
left: number;
|
|
||||||
};
|
|
||||||
isSorted: boolean;
|
|
||||||
heightBetweenNodesCoeff: number;
|
|
||||||
widthBetweenNodesCoeff: number;
|
|
||||||
transitionDuration: number;
|
|
||||||
blinkDuration: number;
|
|
||||||
onClickText: () => void;
|
|
||||||
tooltipOptions: {
|
|
||||||
disabled: boolean;
|
|
||||||
left: number | undefined;
|
|
||||||
top: number | undefined;
|
|
||||||
offset: {
|
|
||||||
left: number;
|
|
||||||
top: number;
|
|
||||||
};
|
|
||||||
style: { [key: string]: Primitive } | undefined;
|
|
||||||
indentationSize?: number;
|
indentationSize?: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -111,8 +72,8 @@ const defaultOptions: Options = {
|
||||||
pushMethod: 'push',
|
pushMethod: 'push',
|
||||||
tree: undefined,
|
tree: undefined,
|
||||||
id: 'd3svg',
|
id: 'd3svg',
|
||||||
style: {
|
chartStyles: {},
|
||||||
node: {
|
nodeStyleOptions: {
|
||||||
colors: {
|
colors: {
|
||||||
default: '#ccc',
|
default: '#ccc',
|
||||||
collapsed: 'lightsteelblue',
|
collapsed: 'lightsteelblue',
|
||||||
|
@ -120,17 +81,16 @@ const defaultOptions: Options = {
|
||||||
},
|
},
|
||||||
radius: 7,
|
radius: 7,
|
||||||
},
|
},
|
||||||
text: {
|
textStyleOptions: {
|
||||||
colors: {
|
colors: {
|
||||||
default: 'black',
|
default: 'black',
|
||||||
hover: 'skyblue',
|
hover: 'skyblue',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
link: {
|
linkStyles: {
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
fill: 'none',
|
fill: 'none',
|
||||||
},
|
},
|
||||||
},
|
|
||||||
size: 500,
|
size: 500,
|
||||||
aspectRatio: 1.0,
|
aspectRatio: 1.0,
|
||||||
initialZoom: 1,
|
initialZoom: 1,
|
||||||
|
@ -156,37 +116,29 @@ const defaultOptions: Options = {
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
},
|
},
|
||||||
style: undefined,
|
styles: undefined,
|
||||||
},
|
},
|
||||||
};
|
} satisfies Options;
|
||||||
|
|
||||||
export interface NodeWithId {
|
export interface InternalNode extends Node {
|
||||||
name: string;
|
_children?: this[] | undefined;
|
||||||
children?: NodeWithId[] | null;
|
id: string | number;
|
||||||
_children?: NodeWithId[] | null;
|
|
||||||
value?: unknown;
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
parent?: NodeWithId;
|
|
||||||
depth?: number;
|
|
||||||
x?: number;
|
|
||||||
y?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NodePosition {
|
interface NodePosition {
|
||||||
parentId: string | null | undefined;
|
parentId: string | number | null;
|
||||||
id: string;
|
id: string | number;
|
||||||
x: number | undefined;
|
x: number;
|
||||||
y: number | undefined;
|
y: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function (
|
export default function (DOMNode: HTMLElement, options: Partial<Options> = {}) {
|
||||||
DOMNode: HTMLElement,
|
|
||||||
options: Partial<InputOptions> = {}
|
|
||||||
) {
|
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
style,
|
chartStyles,
|
||||||
|
nodeStyleOptions,
|
||||||
|
textStyleOptions,
|
||||||
|
linkStyles,
|
||||||
size,
|
size,
|
||||||
aspectRatio,
|
aspectRatio,
|
||||||
initialZoom,
|
initialZoom,
|
||||||
|
@ -202,64 +154,50 @@ export default function (
|
||||||
tree,
|
tree,
|
||||||
tooltipOptions,
|
tooltipOptions,
|
||||||
onClickText,
|
onClickText,
|
||||||
} = deepmerge(defaultOptions, options) as Options;
|
} = deepmerge(defaultOptions, options);
|
||||||
|
|
||||||
const width = size - margin.left - margin.right;
|
const width = size - margin.left - margin.right;
|
||||||
const height = size * aspectRatio - margin.top - margin.bottom;
|
const height = size * aspectRatio - margin.top - margin.bottom;
|
||||||
const fullWidth = size;
|
const fullWidth = size;
|
||||||
const fullHeight = size * aspectRatio;
|
const fullHeight = size * aspectRatio;
|
||||||
|
|
||||||
const attr: { [key: string]: Primitive } = {
|
|
||||||
id,
|
|
||||||
preserveAspectRatio: 'xMinYMin slice',
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!(style as unknown as { [key: string]: Primitive }).width) {
|
|
||||||
attr.width = fullWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!(style as unknown as { [key: string]: Primitive }).width ||
|
|
||||||
!(style as unknown as { [key: string]: Primitive }).height
|
|
||||||
) {
|
|
||||||
attr.viewBox = `0 0 ${fullWidth} ${fullHeight}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const root = d3.select(DOMNode);
|
const root = d3.select(DOMNode);
|
||||||
const zoom = d3.behavior.zoom().scaleExtent([0.1, 3]).scale(initialZoom);
|
const zoom = d3.zoom<SVGSVGElement, unknown>().scaleExtent([0.1, 3]);
|
||||||
const vis = root
|
|
||||||
|
const svgElement = root
|
||||||
.append('svg')
|
.append('svg')
|
||||||
.attr(attr)
|
.attr('id', id)
|
||||||
.style({ cursor: '-webkit-grab', ...style } as unknown as {
|
.attr('preserveAspectRatio', 'xMinYMin slice')
|
||||||
[key: string]: Primitive;
|
.style('cursor', '-webkit-grab');
|
||||||
})
|
|
||||||
|
if (!chartStyles.width) {
|
||||||
|
svgElement.attr('width', fullWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chartStyles.width || !chartStyles.height) {
|
||||||
|
svgElement.attr('viewBox', `0 0 ${fullWidth} ${fullHeight}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(chartStyles)) {
|
||||||
|
svgElement.style(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vis = svgElement
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
.call(zoom.scaleTo, initialZoom)
|
||||||
.call(
|
.call(
|
||||||
zoom.on('zoom', () => {
|
zoom.on('zoom', (event) => {
|
||||||
const { translate, scale } = d3.event as ZoomEvent;
|
const { transform } = event as D3ZoomEvent<SVGSVGElement, unknown>;
|
||||||
vis.attr(
|
vis.attr('transform', transform.toString());
|
||||||
'transform',
|
|
||||||
`translate(${translate.toString()})scale(${scale})`
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.append('g')
|
.append('g')
|
||||||
.attr({
|
.attr(
|
||||||
transform: `translate(${margin.left + style.node.radius}, ${
|
'transform',
|
||||||
|
`translate(${margin.left + nodeStyleOptions.radius}, ${
|
||||||
margin.top
|
margin.top
|
||||||
}) scale(${initialZoom})`,
|
}) scale(${initialZoom})`
|
||||||
});
|
|
||||||
|
|
||||||
let layout = d3.layout.tree().size([width, height]);
|
|
||||||
let data: NodeWithId;
|
|
||||||
|
|
||||||
if (isSorted) {
|
|
||||||
layout.sort((a, b) =>
|
|
||||||
(b as NodeWithId).name.toLowerCase() <
|
|
||||||
(a as NodeWithId).name.toLowerCase()
|
|
||||||
? 1
|
|
||||||
: -1
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
// previousNodePositionsById stores node x and y
|
// previousNodePositionsById stores node x and y
|
||||||
// as well as hierarchy (id / parentId);
|
// as well as hierarchy (id / parentId);
|
||||||
|
@ -277,8 +215,8 @@ export default function (
|
||||||
// of parent ids; once a parent that matches the given filter is found,
|
// of parent ids; once a parent that matches the given filter is found,
|
||||||
// the parent position gets returned
|
// the parent position gets returned
|
||||||
function findParentNodePosition(
|
function findParentNodePosition(
|
||||||
nodePositionsById: { [nodeId: string]: NodePosition },
|
nodePositionsById: { [nodeId: string | number]: NodePosition },
|
||||||
nodeId: string,
|
nodeId: string | number,
|
||||||
filter: (nodePosition: NodePosition) => boolean
|
filter: (nodePosition: NodePosition) => boolean
|
||||||
) {
|
) {
|
||||||
let currentPosition = nodePositionsById[nodeId];
|
let currentPosition = nodePositionsById[nodeId];
|
||||||
|
@ -294,19 +232,18 @@ export default function (
|
||||||
}
|
}
|
||||||
|
|
||||||
return function renderChart(nextState = tree || state) {
|
return function renderChart(nextState = tree || state) {
|
||||||
data = !tree
|
let data = !tree
|
||||||
? // eslint-disable-next-line @typescript-eslint/ban-types
|
? (map2tree(nextState, {
|
||||||
(map2tree(nextState as {}, {
|
|
||||||
key: rootKeyName,
|
key: rootKeyName,
|
||||||
pushMethod,
|
pushMethod,
|
||||||
}) as NodeWithId)
|
}) as InternalNode)
|
||||||
: (nextState as NodeWithId);
|
: (nextState as InternalNode);
|
||||||
|
|
||||||
if (isEmpty(data) || !data.name) {
|
if (isEmpty(data) || !data.name) {
|
||||||
data = {
|
data = {
|
||||||
name: 'error',
|
name: 'error',
|
||||||
message: 'Please provide a state map or a tree structure',
|
message: 'Please provide a state map or a tree structure',
|
||||||
} as unknown as NodeWithId;
|
} as unknown as InternalNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
let nodeIndex = 0;
|
let nodeIndex = 0;
|
||||||
|
@ -334,76 +271,94 @@ export default function (
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
// path generator for links
|
// path generator for links
|
||||||
const diagonal = d3.svg
|
const linkHorizontal = d3
|
||||||
.diagonal<NodePosition>()
|
.linkHorizontal<
|
||||||
.projection((d) => [d.y!, d.x!]);
|
{
|
||||||
|
source: { x: number; y: number };
|
||||||
|
target: { x: number; y: number };
|
||||||
|
},
|
||||||
|
{ x: number; y: number }
|
||||||
|
>()
|
||||||
|
.x((d) => d.y)
|
||||||
|
.y((d) => d.x);
|
||||||
// set tree dimensions and spacing between branches and nodes
|
// set tree dimensions and spacing between branches and nodes
|
||||||
const maxNodeCountByLevel = Math.max(...getNodeGroupByDepthCount(data));
|
const maxNodeCountByLevel = Math.max(...getNodeGroupByDepthCount(data));
|
||||||
|
|
||||||
layout = layout.size([
|
const layout = d3
|
||||||
maxNodeCountByLevel * 25 * heightBetweenNodesCoeff,
|
.tree<InternalNode>()
|
||||||
width,
|
.size([maxNodeCountByLevel * 25 * heightBetweenNodesCoeff, width]);
|
||||||
]);
|
|
||||||
|
|
||||||
const nodes = layout.nodes(data as d3.layout.tree.Node) as NodeWithId[];
|
const rootNode = d3.hierarchy(data);
|
||||||
const links = layout.links(nodes as d3.layout.tree.Node[]);
|
if (isSorted) {
|
||||||
|
rootNode.sort((a, b) =>
|
||||||
|
b.data.name.toLowerCase() < a.data.name.toLowerCase() ? 1 : -1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
nodes.forEach(
|
const rootPointNode = layout(rootNode);
|
||||||
|
const links = rootPointNode.links();
|
||||||
|
|
||||||
|
rootPointNode.each(
|
||||||
(node) =>
|
(node) =>
|
||||||
(node.y = node.depth! * (maxLabelLength * 7 * widthBetweenNodesCoeff))
|
(node.y = node.depth * (maxLabelLength * 7 * widthBetweenNodesCoeff))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const nodes = rootPointNode.descendants();
|
||||||
|
|
||||||
const nodePositions = nodes.map((n) => ({
|
const nodePositions = nodes.map((n) => ({
|
||||||
parentId: n.parent && n.parent.id,
|
parentId: n.parent && n.parent.data.id,
|
||||||
id: n.id,
|
id: n.data.id,
|
||||||
x: n.x,
|
x: n.x,
|
||||||
y: n.y,
|
y: n.y,
|
||||||
}));
|
}));
|
||||||
const nodePositionsById: { [nodeId: string]: NodePosition } = {};
|
const nodePositionsById: { [nodeId: string | number]: NodePosition } = {};
|
||||||
nodePositions.forEach((node) => (nodePositionsById[node.id] = node));
|
nodePositions.forEach((node) => (nodePositionsById[node.id] = node));
|
||||||
|
|
||||||
// process the node selection
|
// process the node selection
|
||||||
const node = vis
|
const node = vis
|
||||||
.selectAll('g.node')
|
.selectAll<SVGGElement, HierarchyPointNode<InternalNode>>('g.node')
|
||||||
.property('__oldData__', (d: NodeWithId) => d)
|
.property('__oldData__', (d) => d)
|
||||||
.data(nodes, (d) => d.id || (d.id = ++nodeIndex as unknown as string));
|
.data(nodes, (d) => d.data.id || (d.data.id = ++nodeIndex));
|
||||||
const nodeEnter = node
|
const nodeEnter = node
|
||||||
.enter()
|
.enter()
|
||||||
.append('g')
|
.append('g')
|
||||||
.attr({
|
.attr('class', 'node')
|
||||||
class: 'node',
|
.attr('transform', (d) => {
|
||||||
transform: (d) => {
|
|
||||||
const position = findParentNodePosition(
|
const position = findParentNodePosition(
|
||||||
nodePositionsById,
|
nodePositionsById,
|
||||||
d.id,
|
d.data.id,
|
||||||
(n) => !!previousNodePositionsById[n.id]
|
(n) => !!previousNodePositionsById[n.id]
|
||||||
);
|
);
|
||||||
const previousPosition =
|
const previousPosition =
|
||||||
(position && previousNodePositionsById[position.id]) ||
|
(position && previousNodePositionsById[position.id]) ||
|
||||||
previousNodePositionsById.root;
|
previousNodePositionsById.root;
|
||||||
return `translate(${previousPosition.y!},${previousPosition.x!})`;
|
return `translate(${previousPosition.y},${previousPosition.x})`;
|
||||||
},
|
|
||||||
})
|
})
|
||||||
.style({
|
.style('fill', textStyleOptions.colors.default)
|
||||||
fill: style.text.colors.default,
|
.style('cursor', 'pointer')
|
||||||
cursor: 'pointer',
|
.on('mouseover', function mouseover() {
|
||||||
|
d3.select(this).style('fill', textStyleOptions.colors.hover);
|
||||||
})
|
})
|
||||||
.on('mouseover', function mouseover(this: EventTarget) {
|
.on('mouseout', function mouseout() {
|
||||||
d3.select(this).style({
|
d3.select(this).style('fill', textStyleOptions.colors.default);
|
||||||
fill: style.text.colors.hover,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.on('mouseout', function mouseout(this: EventTarget) {
|
|
||||||
d3.select(this).style({
|
|
||||||
fill: style.text.colors.default,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!tooltipOptions.disabled) {
|
if (!tooltipOptions.disabled) {
|
||||||
nodeEnter.call(
|
nodeEnter.call(
|
||||||
tooltip<NodeWithId>(d3, 'tooltip', { ...tooltipOptions, root })
|
tooltip<
|
||||||
.text((d, i) => getTooltipString(d, i, tooltipOptions))
|
SVGGElement,
|
||||||
.style(tooltipOptions.style)
|
HierarchyPointNode<InternalNode>,
|
||||||
|
SVGGElement,
|
||||||
|
unknown,
|
||||||
|
HTMLElement,
|
||||||
|
unknown,
|
||||||
|
null,
|
||||||
|
undefined
|
||||||
|
>('tooltip', {
|
||||||
|
...tooltipOptions,
|
||||||
|
root,
|
||||||
|
text: (d) => getTooltipString(d.data, tooltipOptions),
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,77 +367,81 @@ export default function (
|
||||||
const nodeEnterInnerGroup = nodeEnter.append('g');
|
const nodeEnterInnerGroup = nodeEnter.append('g');
|
||||||
nodeEnterInnerGroup
|
nodeEnterInnerGroup
|
||||||
.append('circle')
|
.append('circle')
|
||||||
.attr({
|
.attr('class', 'nodeCircle')
|
||||||
class: 'nodeCircle',
|
.attr('r', 0)
|
||||||
r: 0,
|
.on('click', (event, clickedNode) => {
|
||||||
})
|
if ((event as Event).defaultPrevented) return;
|
||||||
.on('click', (clickedNode) => {
|
toggleChildren(clickedNode.data);
|
||||||
if ((d3.event as Event).defaultPrevented) return;
|
|
||||||
toggleChildren(clickedNode);
|
|
||||||
update();
|
update();
|
||||||
});
|
});
|
||||||
|
|
||||||
nodeEnterInnerGroup
|
nodeEnterInnerGroup
|
||||||
.append('text')
|
.append('text')
|
||||||
.attr({
|
.attr('class', 'nodeText')
|
||||||
class: 'nodeText',
|
.attr('text-anchor', 'middle')
|
||||||
'text-anchor': 'middle',
|
.attr('transform', 'translate(0,0)')
|
||||||
transform: 'translate(0,0)',
|
.attr('dy', '.35em')
|
||||||
dy: '.35em',
|
.style('fill-opacity', 0)
|
||||||
})
|
.text((d) => d.data.name)
|
||||||
.style({
|
.on('click', (_, datum) => {
|
||||||
'fill-opacity': 0,
|
onClickText(datum as unknown as HierarchyPointNode<Node>);
|
||||||
})
|
});
|
||||||
.text((d) => d.name)
|
|
||||||
.on('click', onClickText);
|
const nodeEnterAndUpdate = nodeEnter.merge(node);
|
||||||
|
|
||||||
// update the text to reflect whether node has children or not
|
// update the text to reflect whether node has children or not
|
||||||
node.select('text').text((d) => d.name);
|
nodeEnterAndUpdate.select('text').text((d) => d.data.name);
|
||||||
|
|
||||||
// change the circle fill depending on whether it has children and is collapsed
|
// change the circle fill depending on whether it has children and is collapsed
|
||||||
node.select('circle').style({
|
nodeEnterAndUpdate
|
||||||
stroke: 'black',
|
.select('circle')
|
||||||
'stroke-width': '1.5px',
|
.style('stroke', 'black')
|
||||||
fill: (d) =>
|
.style('stroke-width', '1.5px')
|
||||||
d._children
|
.style('fill', (d) =>
|
||||||
? style.node.colors.collapsed
|
d.data._children && d.data._children.length > 0
|
||||||
: d.children
|
? nodeStyleOptions.colors.collapsed
|
||||||
? style.node.colors.parent
|
: d.data.children && d.data.children.length > 0
|
||||||
: style.node.colors.default,
|
? nodeStyleOptions.colors.parent
|
||||||
});
|
: nodeStyleOptions.colors.default
|
||||||
|
);
|
||||||
|
|
||||||
// transition nodes to their new position
|
// transition nodes to their new position
|
||||||
const nodeUpdate = node
|
const nodeUpdate = nodeEnterAndUpdate
|
||||||
.transition()
|
.transition()
|
||||||
.duration(transitionDuration)
|
.duration(transitionDuration)
|
||||||
.attr({
|
.attr('transform', (d) => `translate(${d.y},${d.x})`);
|
||||||
transform: (d) => `translate(${d.y!},${d.x!})`,
|
|
||||||
});
|
|
||||||
|
|
||||||
// ensure circle radius is correct
|
// ensure circle radius is correct
|
||||||
nodeUpdate.select('circle').attr('r', style.node.radius);
|
nodeUpdate.select('circle').attr('r', nodeStyleOptions.radius);
|
||||||
|
|
||||||
// fade the text in and align it
|
// fade the text in and align it
|
||||||
nodeUpdate
|
nodeUpdate
|
||||||
.select('text')
|
.select<SVGTextElement>('text')
|
||||||
.style('fill-opacity', 1)
|
.style('fill-opacity', 1)
|
||||||
.attr({
|
.attr('transform', function transform(d) {
|
||||||
transform: function transform(this: SVGGraphicsElement, d) {
|
|
||||||
const x =
|
const x =
|
||||||
(d.children || d._children ? -1 : 1) *
|
(((d.data.children ?? d.data._children)?.length ?? 0) > 0
|
||||||
(this.getBBox().width / 2 + style.node.radius + 5);
|
? -1
|
||||||
|
: 1) *
|
||||||
|
(this.getBBox().width / 2 + nodeStyleOptions.radius + 5);
|
||||||
return `translate(${x},0)`;
|
return `translate(${x},0)`;
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// blink updated nodes
|
// blink updated nodes
|
||||||
node
|
nodeEnterAndUpdate
|
||||||
.filter(function flick(this: any, d) {
|
.filter(function flick(
|
||||||
|
this: SVGGElement & {
|
||||||
|
__oldData__?: HierarchyPointNode<InternalNode>;
|
||||||
|
},
|
||||||
|
d
|
||||||
|
) {
|
||||||
// test whether the relevant properties of d match
|
// test whether the relevant properties of d match
|
||||||
// the equivalent property of the oldData
|
// the equivalent property of the oldData
|
||||||
// also test whether the old data exists,
|
// also test whether the old data exists,
|
||||||
// to catch the entering elements!
|
// to catch the entering elements!
|
||||||
return this.__oldData__ && d.value !== this.__oldData__.value;
|
return (
|
||||||
|
!!this.__oldData__ && d.data.value !== this.__oldData__.data.value
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.select('g')
|
.select('g')
|
||||||
.style('opacity', '0.3')
|
.style('opacity', '0.3')
|
||||||
|
@ -492,21 +451,19 @@ export default function (
|
||||||
|
|
||||||
// transition exiting nodes to the parent's new position
|
// transition exiting nodes to the parent's new position
|
||||||
const nodeExit = node
|
const nodeExit = node
|
||||||
.exit()
|
.exit<HierarchyPointNode<InternalNode>>()
|
||||||
.transition()
|
.transition()
|
||||||
.duration(transitionDuration)
|
.duration(transitionDuration)
|
||||||
.attr({
|
.attr('transform', (d) => {
|
||||||
transform: (d) => {
|
|
||||||
const position = findParentNodePosition(
|
const position = findParentNodePosition(
|
||||||
previousNodePositionsById,
|
previousNodePositionsById,
|
||||||
d.id,
|
d.data.id,
|
||||||
(n) => !!nodePositionsById[n.id]
|
(n) => !!nodePositionsById[n.id]
|
||||||
);
|
);
|
||||||
const futurePosition =
|
const futurePosition =
|
||||||
(position && nodePositionsById[position.id]) ||
|
(position && nodePositionsById[position.id]) ||
|
||||||
nodePositionsById.root;
|
nodePositionsById.root;
|
||||||
return `translate(${futurePosition.y!},${futurePosition.x!})`;
|
return `translate(${futurePosition.y},${futurePosition.x})`;
|
||||||
},
|
|
||||||
})
|
})
|
||||||
.remove();
|
.remove();
|
||||||
|
|
||||||
|
@ -516,65 +473,66 @@ export default function (
|
||||||
|
|
||||||
// update the links
|
// update the links
|
||||||
const link = vis
|
const link = vis
|
||||||
.selectAll('path.link')
|
.selectAll<SVGPathElement, HierarchyPointLink<InternalNode>>(
|
||||||
.data(links, (d) => (d.target as NodeWithId).id);
|
'path.link'
|
||||||
|
)
|
||||||
|
.data(links, (d) => d.target.data.id);
|
||||||
|
|
||||||
// enter any new links at the parent's previous position
|
// enter any new links at the parent's previous position
|
||||||
link
|
const linkEnter = link
|
||||||
.enter()
|
.enter()
|
||||||
.insert('path', 'g')
|
.insert('path', 'g')
|
||||||
.attr({
|
.attr('class', 'link')
|
||||||
class: 'link',
|
.attr('d', (d) => {
|
||||||
d: (d) => {
|
|
||||||
const position = findParentNodePosition(
|
const position = findParentNodePosition(
|
||||||
nodePositionsById,
|
nodePositionsById,
|
||||||
(d.target as NodeWithId).id,
|
d.target.data.id,
|
||||||
(n) => !!previousNodePositionsById[n.id]
|
(n) => !!previousNodePositionsById[n.id]
|
||||||
);
|
);
|
||||||
const previousPosition =
|
const previousPosition =
|
||||||
(position && previousNodePositionsById[position.id]) ||
|
(position && previousNodePositionsById[position.id]) ||
|
||||||
previousNodePositionsById.root;
|
previousNodePositionsById.root;
|
||||||
return diagonal({
|
return linkHorizontal({
|
||||||
source: previousPosition,
|
source: previousPosition,
|
||||||
target: previousPosition,
|
target: previousPosition,
|
||||||
} as d3.svg.diagonal.Link<NodePosition>);
|
});
|
||||||
},
|
});
|
||||||
})
|
|
||||||
.style(style.link);
|
for (const [key, value] of Object.entries(linkStyles)) {
|
||||||
|
linkEnter.style(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkEnterAndUpdate = linkEnter.merge(link);
|
||||||
|
|
||||||
// transition links to their new position
|
// transition links to their new position
|
||||||
link
|
linkEnterAndUpdate
|
||||||
.transition()
|
.transition()
|
||||||
.duration(transitionDuration)
|
.duration(transitionDuration)
|
||||||
.attr({
|
.attr('d', linkHorizontal);
|
||||||
d: diagonal as unknown as Primitive,
|
|
||||||
});
|
|
||||||
|
|
||||||
// transition exiting nodes to the parent's new position
|
// transition exiting nodes to the parent's new position
|
||||||
link
|
link
|
||||||
.exit()
|
.exit<HierarchyPointLink<InternalNode>>()
|
||||||
.transition()
|
.transition()
|
||||||
.duration(transitionDuration)
|
.duration(transitionDuration)
|
||||||
.attr({
|
.attr('d', (d) => {
|
||||||
d: (d) => {
|
|
||||||
const position = findParentNodePosition(
|
const position = findParentNodePosition(
|
||||||
previousNodePositionsById,
|
previousNodePositionsById,
|
||||||
(d.target as NodeWithId).id,
|
d.target.data.id,
|
||||||
(n) => !!nodePositionsById[n.id]
|
(n) => !!nodePositionsById[n.id]
|
||||||
);
|
);
|
||||||
const futurePosition =
|
const futurePosition =
|
||||||
(position && nodePositionsById[position.id]) ||
|
(position && nodePositionsById[position.id]) ||
|
||||||
nodePositionsById.root;
|
nodePositionsById.root;
|
||||||
return diagonal({
|
return linkHorizontal({
|
||||||
source: futurePosition,
|
source: futurePosition,
|
||||||
target: futurePosition,
|
target: futurePosition,
|
||||||
});
|
});
|
||||||
},
|
|
||||||
})
|
})
|
||||||
.remove();
|
.remove();
|
||||||
|
|
||||||
// delete the old data once it's no longer needed
|
// delete the old data once it's no longer needed
|
||||||
node.property('__oldData__', null);
|
nodeEnterAndUpdate.property('__oldData__', null);
|
||||||
|
|
||||||
// stash the old positions for transition
|
// stash the old positions for transition
|
||||||
previousNodePositionsById = nodePositionsById;
|
previousNodePositionsById = nodePositionsById;
|
||||||
|
@ -582,4 +540,4 @@ export default function (
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Primitive };
|
export type { Node };
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
import { is, join, pipe, replace } from 'ramda';
|
import { is, join, pipe, replace } from 'ramda';
|
||||||
import sortAndSerialize from './sortAndSerialize';
|
import sortAndSerialize from './sortAndSerialize';
|
||||||
import { NodeWithId } from './tree';
|
import type { InternalNode } from './tree';
|
||||||
|
|
||||||
export function collapseChildren(node: NodeWithId) {
|
export function collapseChildren(node: InternalNode) {
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
node._children = node.children;
|
node._children = node.children;
|
||||||
node._children.forEach(collapseChildren);
|
node._children.forEach(collapseChildren);
|
||||||
node.children = null;
|
node.children = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function expandChildren(node: NodeWithId) {
|
export function expandChildren(node: InternalNode) {
|
||||||
if (node._children) {
|
if (node._children) {
|
||||||
node.children = node._children;
|
node.children = node._children;
|
||||||
node.children.forEach(expandChildren);
|
node.children.forEach(expandChildren);
|
||||||
node._children = null;
|
node._children = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggleChildren(node: NodeWithId) {
|
export function toggleChildren(node: InternalNode) {
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
node._children = node.children;
|
node._children = node.children;
|
||||||
node.children = null;
|
node.children = undefined;
|
||||||
} else if (node._children) {
|
} else if (node._children) {
|
||||||
node.children = node._children;
|
node.children = node._children;
|
||||||
node._children = null;
|
node._children = undefined;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function visit(
|
export function visit(
|
||||||
parent: NodeWithId,
|
parent: InternalNode,
|
||||||
visitFn: (parent: NodeWithId) => void,
|
visitFn: (parent: InternalNode) => void,
|
||||||
childrenFn: (parent: NodeWithId) => NodeWithId[] | null | undefined
|
childrenFn: (parent: InternalNode) => InternalNode[] | null | undefined
|
||||||
) {
|
) {
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
return;
|
return;
|
||||||
|
@ -50,10 +50,10 @@ export function visit(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNodeGroupByDepthCount(rootNode: NodeWithId) {
|
export function getNodeGroupByDepthCount(rootNode: InternalNode) {
|
||||||
const nodeGroupByDepthCount = [1];
|
const nodeGroupByDepthCount = [1];
|
||||||
|
|
||||||
const traverseFrom = function traverseFrom(node: NodeWithId, depth = 0) {
|
const traverseFrom = function traverseFrom(node: InternalNode, depth = 0) {
|
||||||
if (!node.children || node.children.length === 0) {
|
if (!node.children || node.children.length === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -73,11 +73,7 @@ export function getNodeGroupByDepthCount(rootNode: NodeWithId) {
|
||||||
return nodeGroupByDepthCount;
|
return nodeGroupByDepthCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTooltipString(
|
export function getTooltipString(node: InternalNode, { indentationSize = 4 }) {
|
||||||
node: unknown,
|
|
||||||
i: number | undefined,
|
|
||||||
{ indentationSize = 4 }
|
|
||||||
) {
|
|
||||||
if (!is(Object, node)) return '';
|
if (!is(Object, node)) return '';
|
||||||
|
|
||||||
const spacer = join(' ');
|
const spacer = join(' ');
|
||||||
|
@ -89,7 +85,6 @@ export function getTooltipString(
|
||||||
|
|
||||||
if (typeof node.value !== 'undefined') return json2html(node.value);
|
if (typeof node.value !== 'undefined') return json2html(node.value);
|
||||||
if (typeof node.object !== 'undefined') return json2html(node.object);
|
if (typeof node.object !== 'undefined') return json2html(node.object);
|
||||||
if (children && children.length)
|
if (children && children.length) return `childrenCount: ${children.length}`;
|
||||||
return `childrenCount: ${(children as unknown[]).length}`;
|
|
||||||
return 'empty';
|
return 'empty';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
export { tree } from './charts';
|
export { tree } from './charts';
|
||||||
export type { InputOptions, NodeWithId, Primitive } from './charts';
|
export type { HierarchyPointNode, Node, Options, StyleValue } from './charts';
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 3.0.0
|
||||||
|
|
||||||
|
### Major Changes
|
||||||
|
|
||||||
|
- b323f77d: Upgrade D3
|
||||||
|
|
||||||
|
- Remove UMD build.
|
||||||
|
- Upgrade d3 peer dependency from v3 to v7.
|
||||||
|
- Remove `attr` configuration method.
|
||||||
|
- Rename `style` configuration method to `styles` and move to options.
|
||||||
|
- Move `text` configuration method to options.
|
||||||
|
- Remove d3 parameter as first parameter for `tooltip`.
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
|
|
||||||
- Adds ESM build (https://github.com/reduxjs/redux-devtools/pull/997) and switches the default export to a named export in order to ensure that the CommonJS output and the ESM output are [interchangeable](https://rollupjs.org/guide/en/#outputexports):
|
- Adds ESM build (https://github.com/reduxjs/redux-devtools/pull/997) and switches the default export to a named export in order to ensure that the CommonJS output and the ESM output are [interchangeable](https://rollupjs.org/guide/en/#outputexports):
|
||||||
|
|
|
@ -10,45 +10,45 @@ It was created by [@romseguy](https://github.com/romseguy) and merged from [`rom
|
||||||
## Quick usage
|
## Quick usage
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
import { tooltip } from 'd3tooltip';
|
import { tooltip } from 'd3tooltip';
|
||||||
|
|
||||||
const DOMNode = document.getElementById('chart');
|
const DOMNode = document.getElementById('chart');
|
||||||
const root = d3.select(DOMNode);
|
const root = d3.select(DOMNode);
|
||||||
const vis = root.append('svg');
|
const vis = root.append('svg');
|
||||||
|
|
||||||
let options = {
|
const options = {
|
||||||
offset: {left: 30, top: 10}
|
offset: { left: 30, top: 10 },
|
||||||
|
styles: { 'min-width': '50px', 'border-radius': '5px' },
|
||||||
};
|
};
|
||||||
|
|
||||||
vis.selectAll('circle').data(someData).enter()
|
vis
|
||||||
|
.selectAll('circle')
|
||||||
|
.data(someData)
|
||||||
|
.enter()
|
||||||
.append('circle')
|
.append('circle')
|
||||||
.attr('r', 10)
|
.attr('r', 10)
|
||||||
.call(
|
.call(
|
||||||
d3tooltip(d3, 'tooltipClassName', options)
|
d3tooltip('tooltipClassName', {
|
||||||
.text((d, i) => toStringOrHtml(d))
|
...options,
|
||||||
.attr({ 'class': 'anotherClassName' })
|
text: (d) => toStringOrHtml(d),
|
||||||
.style({ 'min-width': '50px', 'border-radius: 5px' })
|
})
|
||||||
)
|
)
|
||||||
.on({
|
.on('mouseover', function () {
|
||||||
mouseover(d, i) {
|
d3.select(this).style('fill', 'skyblue');
|
||||||
d3.select(this).style({
|
})
|
||||||
fill: 'skyblue'
|
.on('mouseout', function () {
|
||||||
});
|
d3.select(this).style('fill', 'black');
|
||||||
},
|
|
||||||
mouseout(d, i) {
|
|
||||||
d3.select(this).style({
|
|
||||||
fill: 'black'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
| -------- | ----------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| -------- | ------------------ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `root` | DOM.Element | `body` | The tooltip will be added as a child of that element. You can also use a D3 [selection](https://github.com/mbostock/d3/wiki/Selections#d3_select) |
|
| `root` | DOM.Element | `body` | The tooltip will be added as a child of that element. You can also use a D3 [selection](https://github.com/mbostock/d3/wiki/Selections#d3_select). |
|
||||||
| `left` | Number | `undefined` | Sets the tooltip `x` absolute position instead of the mouse `x` position, relative to the `root` element |
|
| `left` | Number | `undefined` | Sets the tooltip `x` absolute position instead of the mouse `x` position, relative to the `root` element. |
|
||||||
| `top` | Number | `undefined` | Sets the tooltip `y` absolute position instead of the mouse `y` position, relative to the `root` element |
|
| `top` | Number | `undefined` | Sets the tooltip `y` absolute position instead of the mouse `y` position, relative to the `root` element. |
|
||||||
| `offset` | Object | `{left: 0, top: 0}` | Sets the distance, starting from the cursor position, until the tooltip is rendered. **Warning**: only applicable if you don't provide a `left` or `top` option |
|
| `offset` | Object | `{left: 0, top: 0}` | Sets the distance, starting from the cursor position, until the tooltip is rendered. **Warning**: only applicable if you don't provide a `left` or `top` option. |
|
||||||
|
| `styles` | Object | `{}` | Sets the styles of the tooltip element. |
|
||||||
|
| `text` | String or Function | `''` | Sets the text of the tooltip. Can be a constant `string` or a function that takes the datum and returns a `string`. |
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "d3tooltip",
|
"name": "d3tooltip",
|
||||||
"version": "2.1.0",
|
"version": "3.0.0",
|
||||||
"description": "A highly configurable tooltip for d3",
|
"description": "A highly configurable tooltip for d3",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"d3",
|
"d3",
|
||||||
|
@ -19,18 +19,16 @@
|
||||||
"main": "lib/cjs/index.js",
|
"main": "lib/cjs/index.js",
|
||||||
"module": "lib/esm/index.js",
|
"module": "lib/esm/index.js",
|
||||||
"types": "lib/types/index.d.ts",
|
"types": "lib/types/index.d.ts",
|
||||||
"unpkg": "lib/umd/d3tooltip.umd.js",
|
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm run build:cjs && pnpm run build:esm && pnpm run build:types && pnpm run build:umd",
|
"build": "pnpm run build:cjs && pnpm run build:esm && pnpm run build:types",
|
||||||
"build:cjs": "babel src --extensions \".ts\" --out-dir lib/cjs",
|
"build:cjs": "babel src --extensions \".ts\" --out-dir lib/cjs",
|
||||||
"build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts\" --out-dir lib/esm",
|
"build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts\" --out-dir lib/esm",
|
||||||
"build:types": "tsc --emitDeclarationOnly",
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
"build:umd": "rollup -c",
|
|
||||||
"clean": "rimraf lib",
|
"clean": "rimraf lib",
|
||||||
"lint": "eslint . --ext .ts",
|
"lint": "eslint . --ext .ts",
|
||||||
"type-check": "tsc --noEmit",
|
"type-check": "tsc --noEmit",
|
||||||
|
@ -38,36 +36,25 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint"
|
"prepublish": "pnpm run type-check && pnpm run lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0"
|
||||||
"ramda": "^0.28.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@rollup/plugin-babel": "^6.0.3",
|
"@types/d3": "^7.4.0",
|
||||||
"@rollup/plugin-commonjs": "^24.0.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"@rollup/plugin-terser": "^0.2.1",
|
"d3": "^7.8.2",
|
||||||
"@types/d3": "^3.5.47",
|
"eslint": "^8.35.0",
|
||||||
"@types/node": "^18.11.17",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"@types/ramda": "^0.28.20",
|
"rimraf": "^4.1.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"typescript": "~4.9.5"
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
|
||||||
"d3": "^3.5.17",
|
|
||||||
"eslint": "^8.30.0",
|
|
||||||
"eslint-config-prettier": "^8.5.0",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"rollup": "^3.7.5",
|
|
||||||
"rollup-plugin-typescript2": "^0.34.1",
|
|
||||||
"tslib": "^2.4.1",
|
|
||||||
"typescript": "~4.9.4"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/d3": "^3.5.47",
|
"@types/d3": "^7.4.0",
|
||||||
"d3": "^3.5.17"
|
"d3": "^7.8.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
import typescript from 'rollup-plugin-typescript2';
|
|
||||||
import resolve from '@rollup/plugin-node-resolve';
|
|
||||||
import commonjs from '@rollup/plugin-commonjs';
|
|
||||||
import babel from '@rollup/plugin-babel';
|
|
||||||
import terser from '@rollup/plugin-terser';
|
|
||||||
|
|
||||||
const config = [
|
|
||||||
{
|
|
||||||
input: 'src/index.ts',
|
|
||||||
output: {
|
|
||||||
name: 'd3tooltip',
|
|
||||||
file: 'lib/umd/d3tooltip.js',
|
|
||||||
format: 'umd',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript({
|
|
||||||
tsconfigOverride: { compilerOptions: { declaration: false } },
|
|
||||||
}),
|
|
||||||
resolve(),
|
|
||||||
commonjs(),
|
|
||||||
babel({
|
|
||||||
babelHelpers: 'runtime',
|
|
||||||
extensions: ['.ts'],
|
|
||||||
plugins: ['@babel/plugin-transform-runtime'],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/index.ts',
|
|
||||||
output: {
|
|
||||||
name: 'd3tooltip',
|
|
||||||
file: 'lib/umd/d3tooltip.min.js',
|
|
||||||
format: 'umd',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript({
|
|
||||||
tsconfigOverride: { compilerOptions: { declaration: false } },
|
|
||||||
}),
|
|
||||||
resolve(),
|
|
||||||
commonjs(),
|
|
||||||
babel({
|
|
||||||
babelHelpers: 'runtime',
|
|
||||||
extensions: ['.ts'],
|
|
||||||
plugins: ['@babel/plugin-transform-runtime'],
|
|
||||||
}),
|
|
||||||
terser(),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default config;
|
|
|
@ -1,161 +1,102 @@
|
||||||
import d3Package, { Primitive, Selection } from 'd3';
|
import * as d3 from 'd3';
|
||||||
import { is } from 'ramda';
|
import type { BaseType, Selection } from 'd3';
|
||||||
import utils from './utils';
|
|
||||||
const { prependClass, functor } = utils;
|
|
||||||
|
|
||||||
interface Options<Datum> {
|
export type StyleValue = string | number | boolean;
|
||||||
|
|
||||||
|
interface Options<
|
||||||
|
Datum,
|
||||||
|
RootGElement extends BaseType,
|
||||||
|
RootDatum,
|
||||||
|
RootPElement extends BaseType,
|
||||||
|
RootPDatum
|
||||||
|
> {
|
||||||
left: number | undefined;
|
left: number | undefined;
|
||||||
top: number | undefined;
|
top: number | undefined;
|
||||||
offset: {
|
offset: {
|
||||||
left: number;
|
left: number;
|
||||||
top: number;
|
top: number;
|
||||||
};
|
};
|
||||||
root: Selection<Datum> | undefined;
|
root:
|
||||||
|
| Selection<RootGElement, RootDatum, RootPElement, RootPDatum>
|
||||||
|
| undefined;
|
||||||
|
styles: { [key: string]: StyleValue };
|
||||||
|
text: string | ((datum: Datum) => string);
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: Options<unknown> = {
|
const defaultOptions: Options<unknown, BaseType, unknown, BaseType, unknown> = {
|
||||||
left: undefined, // mouseX
|
left: undefined, // mouseX
|
||||||
top: undefined, // mouseY
|
top: undefined, // mouseY
|
||||||
offset: { left: 0, top: 0 },
|
offset: { left: 0, top: 0 },
|
||||||
root: undefined,
|
root: undefined,
|
||||||
|
styles: {},
|
||||||
|
text: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Tip<Datum> {
|
export function tooltip<
|
||||||
(selection: Selection<Datum>): void;
|
GElement extends BaseType,
|
||||||
attr: (
|
Datum,
|
||||||
this: this,
|
PElement extends BaseType,
|
||||||
d:
|
PDatum,
|
||||||
| string
|
RootGElement extends BaseType,
|
||||||
| {
|
RootDatum,
|
||||||
[key: string]:
|
RootPElement extends BaseType,
|
||||||
| Primitive
|
RootPDatum
|
||||||
| ((datum: Datum, index: number, outerIndex: number) => Primitive);
|
>(
|
||||||
}
|
|
||||||
) => this;
|
|
||||||
style: (
|
|
||||||
this: this,
|
|
||||||
d:
|
|
||||||
| string
|
|
||||||
| {
|
|
||||||
[key: string]:
|
|
||||||
| Primitive
|
|
||||||
| ((datum: Datum, index: number, outerIndex: number) => Primitive);
|
|
||||||
}
|
|
||||||
| undefined
|
|
||||||
) => this;
|
|
||||||
text: (
|
|
||||||
this: this,
|
|
||||||
d: string | ((datum: Datum, index?: number, outerIndex?: number) => string)
|
|
||||||
) => this;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function tooltip<Datum>(
|
|
||||||
d3: typeof d3Package,
|
|
||||||
className = 'tooltip',
|
className = 'tooltip',
|
||||||
options: Partial<Options<Datum>> = {}
|
options: Partial<
|
||||||
): Tip<Datum> {
|
Options<Datum, RootGElement, RootDatum, RootPElement, RootPDatum>
|
||||||
const { left, top, offset, root } = {
|
> = {}
|
||||||
|
) {
|
||||||
|
const { left, top, offset, root, styles, text } = {
|
||||||
...defaultOptions,
|
...defaultOptions,
|
||||||
...options,
|
...options,
|
||||||
} as Options<Datum>;
|
} as Options<Datum, RootGElement, RootDatum, RootPElement, RootPDatum>;
|
||||||
|
|
||||||
let attrs = { class: className };
|
let el: Selection<HTMLDivElement, RootDatum, BaseType, unknown>;
|
||||||
let text: (datum: Datum, index?: number, outerIndex?: number) => string = (
|
const anchor: Selection<
|
||||||
node: Datum
|
RootGElement,
|
||||||
) => '';
|
RootDatum,
|
||||||
let styles = {};
|
RootPElement | HTMLElement,
|
||||||
|
RootPDatum
|
||||||
|
> = root || d3.select<RootGElement, RootDatum>('body');
|
||||||
|
const rootNode = anchor.node()!;
|
||||||
|
|
||||||
let el: Selection<Datum>;
|
return function tip(selection: Selection<GElement, Datum, PElement, PDatum>) {
|
||||||
const anchor = root || d3.select('body');
|
selection.on('mouseover.tip', (event, datum) => {
|
||||||
const rootNode = anchor.node();
|
const [pointerX, pointerY] = d3.pointer(event, rootNode);
|
||||||
|
const [x, y] = [
|
||||||
function tip(selection: Selection<Datum>) {
|
left || pointerX + offset.left,
|
||||||
selection.on('mouseover.tip', (node) => {
|
top || pointerY - offset.top,
|
||||||
const [mouseX, mouseY] = d3.mouse(rootNode);
|
];
|
||||||
const [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
|
|
||||||
|
|
||||||
anchor.selectAll(`div.${className}`).remove();
|
anchor.selectAll(`div.${className}`).remove();
|
||||||
|
|
||||||
el = anchor
|
el = anchor
|
||||||
.append('div')
|
.append('div')
|
||||||
.attr(prependClass(className)(attrs))
|
.attr('class', className)
|
||||||
.style({
|
.style('position', 'absolute')
|
||||||
position: 'absolute',
|
.style('z-index', 1001)
|
||||||
'z-index': 1001,
|
.style('left', `${x}px`)
|
||||||
left: `${x}px`,
|
.style('top', `${y}px`)
|
||||||
top: `${y}px`,
|
.html(typeof text === 'function' ? () => text(datum) : () => text);
|
||||||
...styles,
|
|
||||||
})
|
for (const [key, value] of Object.entries(styles)) {
|
||||||
.html(() => text(node)) as Selection<Datum>;
|
el.style(key, value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
selection.on('mousemove.tip', (node) => {
|
selection.on('mousemove.tip', (event, datum) => {
|
||||||
const [mouseX, mouseY] = d3.mouse(rootNode);
|
const [pointerX, pointerY] = d3.pointer(event, rootNode);
|
||||||
const [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
|
const [x, y] = [
|
||||||
|
left || pointerX + offset.left,
|
||||||
|
top || pointerY - offset.top,
|
||||||
|
];
|
||||||
|
|
||||||
el.style({
|
el.style('left', `${x}px`)
|
||||||
left: `${x}px`,
|
.style('top', `${y}px`)
|
||||||
top: `${y}px`,
|
.html(typeof text === 'function' ? () => text(datum) : () => text);
|
||||||
}).html(() => text(node));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
selection.on('mouseout.tip', () => el.remove());
|
selection.on('mouseout.tip', () => el.remove());
|
||||||
}
|
|
||||||
|
|
||||||
tip.attr = function setAttr(
|
|
||||||
this: typeof tip,
|
|
||||||
d:
|
|
||||||
| string
|
|
||||||
| {
|
|
||||||
[key: string]:
|
|
||||||
| Primitive
|
|
||||||
| ((datum: Datum, index: number, outerIndex: number) => Primitive);
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
if (is(Object, d)) {
|
|
||||||
attrs = {
|
|
||||||
...attrs,
|
|
||||||
...(d as {
|
|
||||||
[key: string]:
|
|
||||||
| Primitive
|
|
||||||
| ((datum: Datum, index: number, outerIndex: number) => Primitive);
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
tip.style = function setStyle(
|
|
||||||
this: typeof tip,
|
|
||||||
d:
|
|
||||||
| string
|
|
||||||
| {
|
|
||||||
[key: string]:
|
|
||||||
| Primitive
|
|
||||||
| ((datum: Datum, index: number, outerIndex: number) => Primitive);
|
|
||||||
}
|
|
||||||
| undefined
|
|
||||||
) {
|
|
||||||
if (is(Object, d)) {
|
|
||||||
styles = {
|
|
||||||
...styles,
|
|
||||||
...(d as {
|
|
||||||
[key: string]:
|
|
||||||
| Primitive
|
|
||||||
| ((datum: Datum, index: number, outerIndex: number) => Primitive);
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
tip.text = function setText(
|
|
||||||
this: typeof tip,
|
|
||||||
d: string | ((datum: Datum, index?: number, outerIndex?: number) => string)
|
|
||||||
) {
|
|
||||||
text = functor(d);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
return tip;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { is } from 'ramda';
|
|
||||||
import { Primitive } from 'd3';
|
|
||||||
|
|
||||||
export default function functor<Datum>(
|
|
||||||
v: string | ((datum: Datum, index?: number, outerIndex?: number) => string)
|
|
||||||
): (datum: Datum, index?: number, outerIndex?: number) => string;
|
|
||||||
export default function functor<Datum>(
|
|
||||||
v:
|
|
||||||
| Primitive
|
|
||||||
| ((datum: Datum, index: number, outerIndex?: number) => Primitive)
|
|
||||||
): (datum: Datum, index?: number, outerIndex?: number) => Primitive;
|
|
||||||
export default function functor<Datum>(
|
|
||||||
v:
|
|
||||||
| Primitive
|
|
||||||
| ((datum: Datum, index: number, outerIndex?: number) => Primitive)
|
|
||||||
): (datum: Datum, index: number, outerIndex?: number) => Primitive {
|
|
||||||
return is(Function, v)
|
|
||||||
? (v as (datum: Datum, index: number, outerIndex?: number) => Primitive)
|
|
||||||
: () => v;
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
import prependClass from './prependClass';
|
|
||||||
import functor from './functor';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
prependClass,
|
|
||||||
functor,
|
|
||||||
};
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { mapObjIndexed, join } from 'ramda';
|
|
||||||
import functor from './functor';
|
|
||||||
import { Primitive } from 'd3';
|
|
||||||
|
|
||||||
export default function prependClass<Datum>(className: string) {
|
|
||||||
return mapObjIndexed(
|
|
||||||
(
|
|
||||||
value:
|
|
||||||
| Primitive
|
|
||||||
| ((datum: Datum, index: number, outerIndex?: number) => Primitive),
|
|
||||||
key
|
|
||||||
) => {
|
|
||||||
if (key === 'class') {
|
|
||||||
const fn = functor(value);
|
|
||||||
|
|
||||||
return (d: Datum, i: number) => {
|
|
||||||
const classNames = fn(d, i);
|
|
||||||
if (classNames !== className) {
|
|
||||||
return join(' ', [className, classNames]);
|
|
||||||
}
|
|
||||||
return classNames;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,5 +1,11 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 3.0.0
|
||||||
|
|
||||||
|
### Major Changes
|
||||||
|
|
||||||
|
- b323f77d: Remove UMD build.
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
|
|
||||||
- Adds ESM build (https://github.com/reduxjs/redux-devtools/pull/997) and switches the default export to a named export in order to ensure that the CommonJS output and the ESM output are [interchangeable](https://rollupjs.org/guide/en/#outputexports):
|
- Adds ESM build (https://github.com/reduxjs/redux-devtools/pull/997) and switches the default export to a named export in order to ensure that the CommonJS output and the ESM output are [interchangeable](https://rollupjs.org/guide/en/#outputexports):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "map2tree",
|
"name": "map2tree",
|
||||||
"version": "2.1.0",
|
"version": "3.0.0",
|
||||||
"description": "Utility for mapping maps to trees",
|
"description": "Utility for mapping maps to trees",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"map2tree",
|
"map2tree",
|
||||||
|
@ -22,18 +22,16 @@
|
||||||
"main": "lib/cjs/index.js",
|
"main": "lib/cjs/index.js",
|
||||||
"module": "lib/esm/index.js",
|
"module": "lib/esm/index.js",
|
||||||
"types": "lib/types/index.d.ts",
|
"types": "lib/types/index.d.ts",
|
||||||
"unpkg": "lib/umd/map2tree.umd.js",
|
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm run build:cjs && pnpm run build:esm && pnpm run build:types && pnpm run build:umd",
|
"build": "pnpm run build:cjs && pnpm run build:esm && pnpm run build:types",
|
||||||
"build:cjs": "babel src --extensions \".ts\" --out-dir lib/cjs",
|
"build:cjs": "babel src --extensions \".ts\" --out-dir lib/cjs",
|
||||||
"build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts\" --out-dir lib/esm",
|
"build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts\" --out-dir lib/esm",
|
||||||
"build:types": "tsc --emitDeclarationOnly",
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
"build:umd": "rollup -c",
|
|
||||||
"clean": "rimraf lib",
|
"clean": "rimraf lib",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"lint": "eslint . --ext .ts",
|
"lint": "eslint . --ext .ts",
|
||||||
|
@ -42,35 +40,26 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"lodash": "^4.17.21"
|
"lodash": "^4.17.21"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@rollup/plugin-babel": "^6.0.3",
|
"@types/jest": "^29.4.0",
|
||||||
"@rollup/plugin-commonjs": "^24.0.0",
|
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
||||||
"@rollup/plugin-terser": "^0.2.1",
|
|
||||||
"@types/jest": "^29.2.4",
|
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/node": "^18.11.17",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"eslint-plugin-jest": "^27.1.7",
|
"immutable": "^4.2.4",
|
||||||
"immutable": "^4.1.0",
|
"jest": "^29.4.3",
|
||||||
"jest": "^29.3.1",
|
"rimraf": "^4.1.3",
|
||||||
"rimraf": "^3.0.2",
|
"ts-jest": "^29.0.5",
|
||||||
"rollup": "^3.7.5",
|
"typescript": "~4.9.5"
|
||||||
"rollup-plugin-typescript2": "^0.34.1",
|
|
||||||
"ts-jest": "^29.0.3",
|
|
||||||
"tslib": "^2.4.1",
|
|
||||||
"typescript": "~4.9.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
import typescript from 'rollup-plugin-typescript2';
|
|
||||||
import resolve from '@rollup/plugin-node-resolve';
|
|
||||||
import commonjs from '@rollup/plugin-commonjs';
|
|
||||||
import babel from '@rollup/plugin-babel';
|
|
||||||
import terser from '@rollup/plugin-terser';
|
|
||||||
|
|
||||||
const config = [
|
|
||||||
{
|
|
||||||
input: 'src/index.ts',
|
|
||||||
output: {
|
|
||||||
name: 'map2tree',
|
|
||||||
file: 'lib/umd/map2tree.js',
|
|
||||||
format: 'umd',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript({
|
|
||||||
tsconfigOverride: { compilerOptions: { declaration: false } },
|
|
||||||
}),
|
|
||||||
resolve(),
|
|
||||||
commonjs(),
|
|
||||||
babel({
|
|
||||||
babelHelpers: 'runtime',
|
|
||||||
extensions: ['.ts'],
|
|
||||||
plugins: ['@babel/plugin-transform-runtime'],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/index.ts',
|
|
||||||
output: {
|
|
||||||
name: 'map2tree',
|
|
||||||
file: 'lib/umd/map2tree.min.js',
|
|
||||||
format: 'umd',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript({
|
|
||||||
tsconfigOverride: { compilerOptions: { declaration: false } },
|
|
||||||
}),
|
|
||||||
resolve(),
|
|
||||||
commonjs(),
|
|
||||||
babel({
|
|
||||||
babelHelpers: 'runtime',
|
|
||||||
extensions: ['.ts'],
|
|
||||||
plugins: ['@babel/plugin-transform-runtime'],
|
|
||||||
}),
|
|
||||||
terser(),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default config;
|
|
|
@ -4,7 +4,8 @@ import mapValues from 'lodash/mapValues';
|
||||||
|
|
||||||
export interface Node {
|
export interface Node {
|
||||||
name: string;
|
name: string;
|
||||||
children?: Node[] | null;
|
children?: this[];
|
||||||
|
object?: unknown;
|
||||||
value?: unknown;
|
value?: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +44,6 @@ function getNode(tree: Node, key: string): Node | null {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function map2tree(
|
export function map2tree(
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
||||||
root: unknown,
|
root: unknown,
|
||||||
options: { key?: string; pushMethod?: 'push' | 'unshift' } = {},
|
options: { key?: string; pushMethod?: 'push' | 'unshift' } = {},
|
||||||
tree: Node = { name: options.key || 'state', children: [] }
|
tree: Node = { name: options.key || 'state', children: [] }
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@types/base16": "^1.0.2",
|
"@types/base16": "^1.0.2",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.191",
|
||||||
"base16": "^1.0.0",
|
"base16": "^1.0.0",
|
||||||
|
@ -48,24 +48,24 @@
|
||||||
"lodash.curry": "^4.1.1"
|
"lodash.curry": "^4.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@types/color": "^3.0.3",
|
"@types/color": "^3.0.3",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/lodash.curry": "^4.1.7",
|
"@types/lodash.curry": "^4.1.7",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-jest": "^27.1.7",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.3",
|
||||||
"jest-environment-jsdom": "^29.3.1",
|
"jest-environment-jsdom": "^29.4.3",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"ts-jest": "^29.0.3",
|
"ts-jest": "^29.0.5",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,34 +11,34 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.7.0",
|
"react-bootstrap": "^2.7.2",
|
||||||
"react-dock": "^0.6.0",
|
"react-dock": "^0.6.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^4.7.1",
|
"react-icons": "^4.7.1",
|
||||||
"react-is": "^18.2.0",
|
"react-is": "^18.2.0",
|
||||||
"styled-components": "^5.3.6"
|
"styled-components": "^5.3.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.14.4",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"babel-loader": "^9.1.0",
|
"babel-loader": "^9.1.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.14",
|
"fork-ts-checker-webpack-plugin": "^8.0.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "~4.9.4",
|
"typescript": "~4.9.5",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-cli": "^5.0.1",
|
"webpack-cli": "^5.0.1",
|
||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.11.1"
|
||||||
|
|
|
@ -39,38 +39,38 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/prop-types": "^15.7.5",
|
"@types/prop-types": "^15.7.5",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/lodash.debounce": "^4.0.7",
|
"@types/lodash.debounce": "^4.0.7",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-jest": "^27.1.7",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.3",
|
||||||
"jest-environment-jsdom": "^29.3.1",
|
"jest-environment-jsdom": "^29.4.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-test-renderer": "^18.2.0",
|
"react-test-renderer": "^18.2.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"ts-jest": "^29.0.3",
|
"ts-jest": "^29.0.5",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
"@types/react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 0.18.0
|
||||||
|
|
||||||
|
### Major Changes
|
||||||
|
|
||||||
|
- 81926f32: Remove UNSAFE method from react-json-tree
|
||||||
|
|
||||||
|
- Replace `shouldExpandNode` with `shouldExpandNodeInitially`. This function is now only called when a node in the tree is first rendered, when before it would update the expanded state of the node if the results of calling `shouldExpandNode` changed between renders. There is no way to replicate the old behavior exactly, but the new behavior is the intended behavior for the use cases within Redux DevTools. Please open an issue if you need a way to programatically control the expanded state of nodes.
|
||||||
|
- Bump the minimum React version from `16.3.0` to `16.8.0` so that `react-json-tree` can use hooks.
|
||||||
|
- Tightened TypeScript prop types to use `unknown` instead of `any` where possible and make the key path array `readonly`.
|
||||||
|
|
||||||
## 0.17.0
|
## 0.17.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
|
@ -139,7 +139,7 @@ Their full signatures are:
|
||||||
|
|
||||||
#### More Options
|
#### More Options
|
||||||
|
|
||||||
- `shouldExpandNode: function(keyPath, data, level)` - determines if node should be expanded (root is expanded by default)
|
- `shouldExpandNodeInitially: function(keyPath, data, level)` - determines if node should be expanded when it first renders (root is expanded by default)
|
||||||
- `hideRoot: boolean` - if `true`, the root node is hidden.
|
- `hideRoot: boolean` - if `true`, the root node is hidden.
|
||||||
- `sortObjectKeys: boolean | function(a, b)` - sorts object keys with compare function (optional). Isn't applied to iterable maps like `Immutable.Map`.
|
- `sortObjectKeys: boolean | function(a, b)` - sorts object keys with compare function (optional). Isn't applied to iterable maps like `Immutable.Map`.
|
||||||
- `postprocessValue: function(value)` - maps `value` to a new `value`
|
- `postprocessValue: function(value)` - maps `value` to a new `value`
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
# react-json-tree-example
|
# react-json-tree-example
|
||||||
|
|
||||||
|
## 1.1.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [81926f32]
|
||||||
|
- react-json-tree@0.18.0
|
||||||
|
|
||||||
## 1.1.7
|
## 1.1.7
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "react-json-tree-example",
|
"name": "react-json-tree-example",
|
||||||
"version": "1.1.7",
|
"version": "1.1.8",
|
||||||
"description": "React-Json-Tree example",
|
"description": "React-Json-Tree example",
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/react-json-tree/examples",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/react-json-tree/examples",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -19,32 +19,32 @@
|
||||||
"type-check": "tsc --noEmit"
|
"type-check": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"immutable": "^4.1.0",
|
"immutable": "^4.2.4",
|
||||||
"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-dom": "^18.2.0",
|
||||||
"react-json-tree": "^0.17.0"
|
"react-json-tree": "^0.18.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.14.4",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"babel-loader": "^9.1.0",
|
"babel-loader": "^9.1.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.14",
|
"fork-ts-checker-webpack-plugin": "^8.0.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "~4.9.4",
|
"typescript": "~4.9.5",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-cli": "^5.0.1",
|
"webpack-cli": "^5.0.1",
|
||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.11.1"
|
||||||
|
|
|
@ -178,7 +178,7 @@ const App = () => (
|
||||||
<span role="img" aria-label="mellow">
|
<span role="img" aria-label="mellow">
|
||||||
😐
|
😐
|
||||||
</span>{' '}
|
</span>{' '}
|
||||||
{raw}{' '}
|
{raw as string}{' '}
|
||||||
<span role="img" aria-label="mellow">
|
<span role="img" aria-label="mellow">
|
||||||
😐
|
😐
|
||||||
</span>
|
</span>
|
||||||
|
@ -194,7 +194,11 @@ const App = () => (
|
||||||
</div>
|
</div>
|
||||||
<p>Collapsed root node</p>
|
<p>Collapsed root node</p>
|
||||||
<div>
|
<div>
|
||||||
<JSONTree data={data} theme={theme} shouldExpandNode={() => false} />
|
<JSONTree
|
||||||
|
data={data}
|
||||||
|
theme={theme}
|
||||||
|
shouldExpandNodeInitially={() => false}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "react-json-tree",
|
"name": "react-json-tree",
|
||||||
"version": "0.17.0",
|
"version": "0.18.0",
|
||||||
"description": "React JSON Viewer Component, Extracted from redux-devtools",
|
"description": "React JSON Viewer Component, Extracted from redux-devtools",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
|
@ -45,47 +45,45 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/prop-types": "^15.7.5",
|
|
||||||
"prop-types": "^15.8.1",
|
|
||||||
"react-base16-styling": "^0.9.1"
|
"react-base16-styling": "^0.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@rollup/plugin-babel": "^6.0.3",
|
"@rollup/plugin-babel": "^6.0.3",
|
||||||
"@rollup/plugin-commonjs": "^24.0.0",
|
"@rollup/plugin-commonjs": "^24.0.1",
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||||
"@rollup/plugin-terser": "^0.2.1",
|
"@rollup/plugin-terser": "^0.4.0",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.14.4",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-jest": "^27.1.7",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-test-renderer": "^18.2.0",
|
"react-test-renderer": "^18.2.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"rollup": "^3.7.5",
|
"rollup": "^3.18.0",
|
||||||
"rollup-plugin-typescript2": "^0.34.1",
|
"rollup-plugin-typescript2": "^0.34.1",
|
||||||
"ts-jest": "^29.0.3",
|
"ts-jest": "^29.0.5",
|
||||||
"tslib": "^2.4.1",
|
"tslib": "^2.5.0",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||||
"react": "^16.3.0 || ^17.0.0 || ^18.0.0"
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +1,39 @@
|
||||||
import React from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import JSONArrow from './JSONArrow';
|
import JSONArrow from './JSONArrow';
|
||||||
import { CircularPropsPassedThroughItemRange } from './types';
|
import type { CircularCache, CommonInternalProps } from './types';
|
||||||
|
|
||||||
interface Props extends CircularPropsPassedThroughItemRange {
|
interface Props extends CommonInternalProps {
|
||||||
data: any;
|
data: unknown;
|
||||||
nodeType: string;
|
nodeType: string;
|
||||||
from: number;
|
from: number;
|
||||||
to: number;
|
to: number;
|
||||||
renderChildNodes: (props: Props, from: number, to: number) => React.ReactNode;
|
renderChildNodes: (props: Props, from: number, to: number) => React.ReactNode;
|
||||||
|
circularCache: CircularCache;
|
||||||
|
level: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
export default function ItemRange(props: Props) {
|
||||||
expanded: boolean;
|
const { styling, from, to, renderChildNodes, nodeType } = props;
|
||||||
}
|
|
||||||
|
|
||||||
export default class ItemRange extends React.Component<Props, State> {
|
const [expanded, setExpanded] = useState<boolean>(false);
|
||||||
static propTypes = {
|
const handleClick = useCallback(() => {
|
||||||
styling: PropTypes.func.isRequired,
|
setExpanded(!expanded);
|
||||||
from: PropTypes.number.isRequired,
|
}, [expanded]);
|
||||||
to: PropTypes.number.isRequired,
|
|
||||||
renderChildNodes: PropTypes.func.isRequired,
|
|
||||||
nodeType: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
return expanded ? (
|
||||||
super(props);
|
<div {...styling('itemRange', expanded)}>
|
||||||
this.state = { expanded: false };
|
{renderChildNodes(props, from, to)}
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { styling, from, to, renderChildNodes, nodeType } = this.props;
|
|
||||||
|
|
||||||
return this.state.expanded ? (
|
|
||||||
<div {...styling('itemRange', this.state.expanded)}>
|
|
||||||
{renderChildNodes(this.props, from, to)}
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div {...styling('itemRange', expanded)} onClick={handleClick}>
|
||||||
{...styling('itemRange', this.state.expanded)}
|
|
||||||
onClick={this.handleClick}
|
|
||||||
>
|
|
||||||
<JSONArrow
|
<JSONArrow
|
||||||
nodeType={nodeType}
|
nodeType={nodeType}
|
||||||
styling={styling}
|
styling={styling}
|
||||||
expanded={false}
|
expanded={false}
|
||||||
onClick={this.handleClick}
|
onClick={handleClick}
|
||||||
arrowStyle="double"
|
arrowStyle="double"
|
||||||
/>
|
/>
|
||||||
{`${from} ... ${to}`}
|
{`${from} ... ${to}`}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick = () => {
|
|
||||||
this.setState({ expanded: !this.state.expanded });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,35 +1,30 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import JSONNestedNode from './JSONNestedNode';
|
import JSONNestedNode from './JSONNestedNode';
|
||||||
import { CircularPropsPassedThroughJSONNode } from './types';
|
import type { CommonInternalProps } from './types';
|
||||||
|
|
||||||
// Returns the "n Items" string for this node,
|
// Returns the "n Items" string for this node,
|
||||||
// generating and caching it if it hasn't been created yet.
|
// generating and caching it if it hasn't been created yet.
|
||||||
function createItemString(data: any) {
|
function createItemString(data: unknown) {
|
||||||
return `${(data as unknown[]).length} ${
|
return `${(data as unknown[]).length} ${
|
||||||
(data as unknown[]).length !== 1 ? 'items' : 'item'
|
(data as unknown[]).length !== 1 ? 'items' : 'item'
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props extends CircularPropsPassedThroughJSONNode {
|
interface Props extends CommonInternalProps {
|
||||||
data: any;
|
data: unknown;
|
||||||
nodeType: string;
|
nodeType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configures <JSONNestedNode> to render an Array
|
// Configures <JSONNestedNode> to render an Array
|
||||||
const JSONArrayNode: React.FunctionComponent<Props> = ({ data, ...props }) => (
|
export default function JSONArrayNode({ data, ...props }: Props) {
|
||||||
|
return (
|
||||||
<JSONNestedNode
|
<JSONNestedNode
|
||||||
{...props}
|
{...props}
|
||||||
data={data}
|
data={data}
|
||||||
nodeType="Array"
|
nodeType="Array"
|
||||||
nodeTypeIndicator="[]"
|
nodeTypeIndicator="[]"
|
||||||
createItemString={createItemString}
|
createItemString={createItemString}
|
||||||
expandable={data.length > 0}
|
expandable={(data as unknown[]).length > 0}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
JSONArrayNode.propTypes = {
|
|
||||||
data: PropTypes.array,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default JSONArrayNode;
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import type { StylingFunction } from 'react-base16-styling';
|
||||||
import { StylingFunction } from 'react-base16-styling';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
styling: StylingFunction;
|
styling: StylingFunction;
|
||||||
|
@ -10,13 +9,14 @@ interface Props {
|
||||||
onClick: React.MouseEventHandler<HTMLDivElement>;
|
onClick: React.MouseEventHandler<HTMLDivElement>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const JSONArrow: React.FunctionComponent<Props> = ({
|
export default function JSONArrow({
|
||||||
styling,
|
styling,
|
||||||
arrowStyle,
|
arrowStyle = 'single',
|
||||||
expanded,
|
expanded,
|
||||||
nodeType,
|
nodeType,
|
||||||
onClick,
|
onClick,
|
||||||
}) => (
|
}: Props) {
|
||||||
|
return (
|
||||||
<div {...styling('arrowContainer', arrowStyle)} onClick={onClick}>
|
<div {...styling('arrowContainer', arrowStyle)} onClick={onClick}>
|
||||||
<div {...styling(['arrow', 'arrowSign'], nodeType, expanded, arrowStyle)}>
|
<div {...styling(['arrow', 'arrowSign'], nodeType, expanded, arrowStyle)}>
|
||||||
{'\u25B6'}
|
{'\u25B6'}
|
||||||
|
@ -26,17 +26,4 @@ const JSONArrow: React.FunctionComponent<Props> = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
JSONArrow.propTypes = {
|
|
||||||
styling: PropTypes.func.isRequired,
|
|
||||||
arrowStyle: PropTypes.oneOf(['single', 'double']),
|
|
||||||
expanded: PropTypes.bool.isRequired,
|
|
||||||
nodeType: PropTypes.string.isRequired,
|
|
||||||
onClick: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
JSONArrow.defaultProps = {
|
|
||||||
arrowStyle: 'single',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default JSONArrow;
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import JSONNestedNode from './JSONNestedNode';
|
import JSONNestedNode from './JSONNestedNode';
|
||||||
import { CircularPropsPassedThroughJSONNode } from './types';
|
import type { CommonInternalProps } from './types';
|
||||||
|
|
||||||
// Returns the "n Items" string for this node,
|
// Returns the "n Items" string for this node,
|
||||||
// generating and caching it if it hasn't been created yet.
|
// generating and caching it if it hasn't been created yet.
|
||||||
|
@ -22,21 +22,20 @@ function createItemString(data: any, limit: number) {
|
||||||
return `${hasMore ? '>' : ''}${count} ${count !== 1 ? 'entries' : 'entry'}`;
|
return `${hasMore ? '>' : ''}${count} ${count !== 1 ? 'entries' : 'entry'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props extends CircularPropsPassedThroughJSONNode {
|
interface Props extends CommonInternalProps {
|
||||||
data: any;
|
data: unknown;
|
||||||
nodeType: string;
|
nodeType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configures <JSONNestedNode> to render an iterable
|
// Configures <JSONNestedNode> to render an iterable
|
||||||
const JSONIterableNode: React.FunctionComponent<Props> = ({ ...props }) => {
|
export default function JSONIterableNode(props: Props) {
|
||||||
return (
|
return (
|
||||||
<JSONNestedNode
|
<JSONNestedNode
|
||||||
{...props}
|
{...props}
|
||||||
nodeType="Iterable"
|
nodeType="Iterable"
|
||||||
nodeTypeIndicator="()"
|
nodeTypeIndicator="()"
|
||||||
createItemString={createItemString}
|
createItemString={createItemString}
|
||||||
|
expandable
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default JSONIterableNode;
|
|
||||||
|
|
|
@ -1,22 +1,19 @@
|
||||||
import React from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import JSONArrow from './JSONArrow';
|
import JSONArrow from './JSONArrow';
|
||||||
import getCollectionEntries from './getCollectionEntries';
|
import getCollectionEntries from './getCollectionEntries';
|
||||||
import JSONNode from './JSONNode';
|
import JSONNode from './JSONNode';
|
||||||
import ItemRange from './ItemRange';
|
import ItemRange from './ItemRange';
|
||||||
import {
|
import type { CircularCache, CommonInternalProps } from './types';
|
||||||
CircularPropsPassedThroughJSONNestedNode,
|
|
||||||
CircularPropsPassedThroughRenderChildNodes,
|
|
||||||
} from './types';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders nested values (eg. objects, arrays, lists, etc.)
|
* Renders nested values (eg. objects, arrays, lists, etc.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export interface RenderChildNodesProps
|
export interface RenderChildNodesProps extends CommonInternalProps {
|
||||||
extends CircularPropsPassedThroughRenderChildNodes {
|
data: unknown;
|
||||||
data: any;
|
|
||||||
nodeType: string;
|
nodeType: string;
|
||||||
|
circularCache: CircularCache;
|
||||||
|
level: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Range {
|
interface Range {
|
||||||
|
@ -26,7 +23,7 @@ interface Range {
|
||||||
|
|
||||||
interface Entry {
|
interface Entry {
|
||||||
key: string | number;
|
key: string | number;
|
||||||
value: any;
|
value: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRange(rangeOrEntry: Range | Entry): rangeOrEntry is Range {
|
function isRange(rangeOrEntry: Range | Entry): rangeOrEntry is Range {
|
||||||
|
@ -89,98 +86,45 @@ function renderChildNodes(
|
||||||
return childNodes;
|
return childNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props extends CircularPropsPassedThroughJSONNestedNode {
|
interface Props extends CommonInternalProps {
|
||||||
data: any;
|
data: unknown;
|
||||||
nodeType: string;
|
nodeType: string;
|
||||||
nodeTypeIndicator: string;
|
nodeTypeIndicator: string;
|
||||||
createItemString: (data: any, collectionLimit: number) => string;
|
createItemString: (data: unknown, collectionLimit: number) => string;
|
||||||
expandable: boolean;
|
expandable: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
export default function JSONNestedNode(props: Props) {
|
||||||
expanded: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStateFromProps(props: Props) {
|
|
||||||
// calculate individual node expansion if necessary
|
|
||||||
const expanded = !props.isCircular
|
|
||||||
? props.shouldExpandNode(props.keyPath, props.data, props.level)
|
|
||||||
: false;
|
|
||||||
return {
|
|
||||||
expanded,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class JSONNestedNode extends React.Component<Props, State> {
|
|
||||||
static propTypes = {
|
|
||||||
getItemString: PropTypes.func.isRequired,
|
|
||||||
nodeTypeIndicator: PropTypes.any,
|
|
||||||
nodeType: PropTypes.string.isRequired,
|
|
||||||
data: PropTypes.any,
|
|
||||||
hideRoot: PropTypes.bool.isRequired,
|
|
||||||
createItemString: PropTypes.func.isRequired,
|
|
||||||
styling: PropTypes.func.isRequired,
|
|
||||||
collectionLimit: PropTypes.number,
|
|
||||||
keyPath: PropTypes.arrayOf(
|
|
||||||
PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
|
||||||
).isRequired,
|
|
||||||
labelRenderer: PropTypes.func.isRequired,
|
|
||||||
shouldExpandNode: PropTypes.func,
|
|
||||||
level: PropTypes.number.isRequired,
|
|
||||||
sortObjectKeys: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
|
|
||||||
isCircular: PropTypes.bool,
|
|
||||||
expandable: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
data: [],
|
|
||||||
circularCache: [],
|
|
||||||
level: 0,
|
|
||||||
expandable: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
this.state = getStateFromProps(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps(nextProps: Props) {
|
|
||||||
const nextState = getStateFromProps(nextProps);
|
|
||||||
if (getStateFromProps(this.props).expanded !== nextState.expanded) {
|
|
||||||
this.setState(nextState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: Props, nextState: State) {
|
|
||||||
return (
|
|
||||||
!!Object.keys(nextProps).find(
|
|
||||||
(key) =>
|
|
||||||
key !== 'circularCache' &&
|
|
||||||
(key === 'keyPath'
|
|
||||||
? nextProps[key].join('/') !== this.props[key].join('/')
|
|
||||||
: nextProps[key as keyof Props] !== this.props[key as keyof Props])
|
|
||||||
) || nextState.expanded !== this.state.expanded
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
const {
|
||||||
getItemString,
|
circularCache = [],
|
||||||
nodeTypeIndicator,
|
|
||||||
nodeType,
|
|
||||||
data,
|
|
||||||
hideRoot,
|
|
||||||
createItemString,
|
|
||||||
styling,
|
|
||||||
collectionLimit,
|
collectionLimit,
|
||||||
|
createItemString,
|
||||||
|
data,
|
||||||
|
expandable,
|
||||||
|
getItemString,
|
||||||
|
hideRoot,
|
||||||
|
isCircular,
|
||||||
keyPath,
|
keyPath,
|
||||||
labelRenderer,
|
labelRenderer,
|
||||||
expandable,
|
level = 0,
|
||||||
} = this.props;
|
nodeType,
|
||||||
const { expanded } = this.state;
|
nodeTypeIndicator,
|
||||||
|
shouldExpandNodeInitially,
|
||||||
|
styling,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const [expanded, setExpanded] = useState<boolean>(
|
||||||
|
// calculate individual node expansion if necessary
|
||||||
|
isCircular ? false : shouldExpandNodeInitially(keyPath, data, level)
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleClick = useCallback(() => {
|
||||||
|
if (expandable) setExpanded(!expanded);
|
||||||
|
}, [expandable, expanded]);
|
||||||
|
|
||||||
const renderedChildren =
|
const renderedChildren =
|
||||||
expanded || (hideRoot && this.props.level === 0)
|
expanded || (hideRoot && level === 0)
|
||||||
? renderChildNodes({ ...this.props, level: this.props.level + 1 })
|
? renderChildNodes({ ...props, circularCache, level: level + 1 })
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const itemType = (
|
const itemType = (
|
||||||
|
@ -210,18 +154,18 @@ export default class JSONNestedNode extends React.Component<Props, State> {
|
||||||
styling={styling}
|
styling={styling}
|
||||||
nodeType={nodeType}
|
nodeType={nodeType}
|
||||||
expanded={expanded}
|
expanded={expanded}
|
||||||
onClick={this.handleClick}
|
onClick={handleClick}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<label
|
<label
|
||||||
{...styling(['label', 'nestedNodeLabel'], ...stylingArgs)}
|
{...styling(['label', 'nestedNodeLabel'], ...stylingArgs)}
|
||||||
onClick={this.handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
{labelRenderer(...stylingArgs)}
|
{labelRenderer(...stylingArgs)}
|
||||||
</label>
|
</label>
|
||||||
<span
|
<span
|
||||||
{...styling('nestedNodeItemString', ...stylingArgs)}
|
{...styling('nestedNodeItemString', ...stylingArgs)}
|
||||||
onClick={this.handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
{renderedItemString}
|
{renderedItemString}
|
||||||
</span>
|
</span>
|
||||||
|
@ -231,10 +175,3 @@ export default class JSONNestedNode extends React.Component<Props, State> {
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick = () => {
|
|
||||||
if (this.props.expandable) {
|
|
||||||
this.setState({ expanded: !this.state.expanded });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import objType from './objType';
|
import objType from './objType';
|
||||||
import JSONObjectNode from './JSONObjectNode';
|
import JSONObjectNode from './JSONObjectNode';
|
||||||
import JSONArrayNode from './JSONArrayNode';
|
import JSONArrayNode from './JSONArrayNode';
|
||||||
import JSONIterableNode from './JSONIterableNode';
|
import JSONIterableNode from './JSONIterableNode';
|
||||||
import JSONValueNode from './JSONValueNode';
|
import JSONValueNode from './JSONValueNode';
|
||||||
import { CircularPropsPassedThroughJSONNode } from './types';
|
import type { CommonInternalProps } from './types';
|
||||||
|
|
||||||
interface Props extends CircularPropsPassedThroughJSONNode {
|
interface Props extends CommonInternalProps {
|
||||||
keyPath: (string | number)[];
|
value: unknown;
|
||||||
value: any;
|
|
||||||
isCustomNode: (value: any) => boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const JSONNode: React.FunctionComponent<Props> = ({
|
export default function JSONNode({
|
||||||
getItemString,
|
getItemString,
|
||||||
keyPath,
|
keyPath,
|
||||||
labelRenderer,
|
labelRenderer,
|
||||||
|
@ -22,7 +19,7 @@ const JSONNode: React.FunctionComponent<Props> = ({
|
||||||
valueRenderer,
|
valueRenderer,
|
||||||
isCustomNode,
|
isCustomNode,
|
||||||
...rest
|
...rest
|
||||||
}) => {
|
}: Props) {
|
||||||
const nodeType = isCustomNode(value) ? 'Custom' : objType(value);
|
const nodeType = isCustomNode(value) ? 'Custom' : objType(value);
|
||||||
|
|
||||||
const simpleNodeProps = {
|
const simpleNodeProps = {
|
||||||
|
@ -102,18 +99,4 @@ const JSONNode: React.FunctionComponent<Props> = ({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
JSONNode.propTypes = {
|
|
||||||
getItemString: PropTypes.func.isRequired,
|
|
||||||
keyPath: PropTypes.arrayOf(
|
|
||||||
PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
|
|
||||||
).isRequired,
|
|
||||||
labelRenderer: PropTypes.func.isRequired,
|
|
||||||
styling: PropTypes.func.isRequired,
|
|
||||||
value: PropTypes.any,
|
|
||||||
valueRenderer: PropTypes.func.isRequired,
|
|
||||||
isCustomNode: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default JSONNode;
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import JSONNestedNode from './JSONNestedNode';
|
import JSONNestedNode from './JSONNestedNode';
|
||||||
import { CircularPropsPassedThroughJSONNode } from './types';
|
import type { CommonInternalProps } from './types';
|
||||||
|
|
||||||
// Returns the "n Items" string for this node,
|
// Returns the "n Items" string for this node,
|
||||||
// generating and caching it if it hasn't been created yet.
|
// generating and caching it if it hasn't been created yet.
|
||||||
function createItemString(data: any) {
|
function createItemString(data: unknown) {
|
||||||
const len = Object.getOwnPropertyNames(data).length;
|
const len = Object.getOwnPropertyNames(data).length;
|
||||||
return `${len} ${len !== 1 ? 'keys' : 'key'}`;
|
return `${len} ${len !== 1 ? 'keys' : 'key'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props extends CircularPropsPassedThroughJSONNode {
|
interface Props extends CommonInternalProps {
|
||||||
data: any;
|
data: unknown;
|
||||||
nodeType: string;
|
nodeType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configures <JSONNestedNode> to render an Object
|
// Configures <JSONNestedNode> to render an Object
|
||||||
const JSONObjectNode: React.FunctionComponent<Props> = ({ data, ...props }) => (
|
export default function JSONObjectNode({ data, ...props }: Props) {
|
||||||
|
return (
|
||||||
<JSONNestedNode
|
<JSONNestedNode
|
||||||
{...props}
|
{...props}
|
||||||
data={data}
|
data={data}
|
||||||
|
@ -26,10 +26,4 @@ const JSONObjectNode: React.FunctionComponent<Props> = ({ data, ...props }) => (
|
||||||
expandable={Object.getOwnPropertyNames(data).length > 0}
|
expandable={Object.getOwnPropertyNames(data).length > 0}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
JSONObjectNode.propTypes = {
|
|
||||||
data: PropTypes.object,
|
|
||||||
nodeType: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default JSONObjectNode;
|
|
||||||
|
|
|
@ -1,18 +1,30 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import type {
|
||||||
import { JSONValueNodeCircularPropsProvidedByJSONNode } from './types';
|
GetItemString,
|
||||||
|
Key,
|
||||||
|
KeyPath,
|
||||||
|
LabelRenderer,
|
||||||
|
Styling,
|
||||||
|
ValueRenderer,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders simple values (eg. strings, numbers, booleans, etc)
|
* Renders simple values (eg. strings, numbers, booleans, etc)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface Props extends JSONValueNodeCircularPropsProvidedByJSONNode {
|
interface Props {
|
||||||
|
getItemString: GetItemString;
|
||||||
|
key: Key;
|
||||||
|
keyPath: KeyPath;
|
||||||
|
labelRenderer: LabelRenderer;
|
||||||
nodeType: string;
|
nodeType: string;
|
||||||
value: any;
|
styling: Styling;
|
||||||
valueGetter?: (value: any) => any;
|
value: unknown;
|
||||||
|
valueRenderer: ValueRenderer;
|
||||||
|
valueGetter?: (value: any) => unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
const JSONValueNode: React.FunctionComponent<Props> = ({
|
export default function JSONValueNode({
|
||||||
nodeType,
|
nodeType,
|
||||||
styling,
|
styling,
|
||||||
labelRenderer,
|
labelRenderer,
|
||||||
|
@ -20,7 +32,8 @@ const JSONValueNode: React.FunctionComponent<Props> = ({
|
||||||
valueRenderer,
|
valueRenderer,
|
||||||
value,
|
value,
|
||||||
valueGetter = (value) => value,
|
valueGetter = (value) => value,
|
||||||
}) => (
|
}: Props) {
|
||||||
|
return (
|
||||||
<li {...styling('value', nodeType, keyPath)}>
|
<li {...styling('value', nodeType, keyPath)}>
|
||||||
<label {...styling(['label', 'valueLabel'], nodeType, keyPath)}>
|
<label {...styling(['label', 'valueLabel'], nodeType, keyPath)}>
|
||||||
{labelRenderer(keyPath, nodeType, false, false)}
|
{labelRenderer(keyPath, nodeType, false, false)}
|
||||||
|
@ -30,17 +43,4 @@ const JSONValueNode: React.FunctionComponent<Props> = ({
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
JSONValueNode.propTypes = {
|
|
||||||
nodeType: PropTypes.string.isRequired,
|
|
||||||
styling: PropTypes.func.isRequired,
|
|
||||||
labelRenderer: PropTypes.func.isRequired,
|
|
||||||
keyPath: PropTypes.arrayOf(
|
|
||||||
PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
|
|
||||||
).isRequired,
|
|
||||||
valueRenderer: PropTypes.func.isRequired,
|
|
||||||
value: PropTypes.any,
|
|
||||||
valueGetter: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default JSONValueNode;
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import type { CurriedFunction1 } from 'lodash';
|
import type { CurriedFunction1 } from 'lodash';
|
||||||
import {
|
import { createStyling } from 'react-base16-styling';
|
||||||
|
import type {
|
||||||
Base16Theme,
|
Base16Theme,
|
||||||
createStyling,
|
|
||||||
StylingConfig,
|
StylingConfig,
|
||||||
|
StylingFunction,
|
||||||
|
Theme,
|
||||||
} from 'react-base16-styling';
|
} from 'react-base16-styling';
|
||||||
import solarized from './themes/solarized';
|
import solarized from './themes/solarized';
|
||||||
import { StylingFunction, Theme } from 'react-base16-styling/src';
|
|
||||||
|
|
||||||
const colorMap = (theme: Base16Theme) => ({
|
const colorMap = (theme: Base16Theme) => ({
|
||||||
BACKGROUND_COLOR: theme.base00,
|
BACKGROUND_COLOR: theme.base00,
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
function getLength(type: string, collection: any) {
|
import type { SortObjectKeys } from './types';
|
||||||
|
|
||||||
|
function getLength(type: string, collection: unknown) {
|
||||||
if (type === 'Object') {
|
if (type === 'Object') {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
return Object.keys(collection as {}).length;
|
return Object.keys(collection as {}).length;
|
||||||
|
@ -9,17 +11,17 @@ function getLength(type: string, collection: any) {
|
||||||
return Infinity;
|
return Infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isIterableMap(collection: any) {
|
function isIterableMap(collection: unknown) {
|
||||||
return typeof (collection as Map<any, any>).set === 'function';
|
return typeof (collection as Map<unknown, unknown>).set === 'function';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEntries(
|
function getEntries(
|
||||||
type: string,
|
type: string,
|
||||||
collection: any,
|
collection: any,
|
||||||
sortObjectKeys?: ((a: any, b: any) => number) | boolean | undefined,
|
sortObjectKeys: SortObjectKeys,
|
||||||
from = 0,
|
from = 0,
|
||||||
to = Infinity
|
to = Infinity
|
||||||
): { entries: { key: string | number; value: any }[]; hasMore?: boolean } {
|
): { entries: { key: string | number; value: unknown }[]; hasMore?: boolean } {
|
||||||
let res;
|
let res;
|
||||||
|
|
||||||
if (type === 'Object') {
|
if (type === 'Object') {
|
||||||
|
@ -95,8 +97,8 @@ function getRanges(from: number, to: number, limit: number) {
|
||||||
|
|
||||||
export default function getCollectionEntries(
|
export default function getCollectionEntries(
|
||||||
type: string,
|
type: string,
|
||||||
collection: any,
|
collection: unknown,
|
||||||
sortObjectKeys: ((a: any, b: any) => number) | boolean | undefined,
|
sortObjectKeys: SortObjectKeys,
|
||||||
limit: number,
|
limit: number,
|
||||||
from = 0,
|
from = 0,
|
||||||
to = Infinity
|
to = Infinity
|
||||||
|
|
|
@ -3,177 +3,88 @@
|
||||||
// Dave Vedder <veddermatic@gmail.com> http://www.eskimospy.com/
|
// Dave Vedder <veddermatic@gmail.com> http://www.eskimospy.com/
|
||||||
// port by Daniele Zannotti http://www.github.com/dzannotti <dzannotti@me.com>
|
// port by Daniele Zannotti http://www.github.com/dzannotti <dzannotti@me.com>
|
||||||
|
|
||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import JSONNode from './JSONNode';
|
import JSONNode from './JSONNode';
|
||||||
import createStylingFromTheme from './createStylingFromTheme';
|
import createStylingFromTheme from './createStylingFromTheme';
|
||||||
import { invertTheme } from 'react-base16-styling';
|
import { invertTheme } from 'react-base16-styling';
|
||||||
|
import type { StylingValue, Theme } from 'react-base16-styling';
|
||||||
import type {
|
import type {
|
||||||
StylingConfig,
|
CommonExternalProps,
|
||||||
StylingFunction,
|
GetItemString,
|
||||||
StylingValue,
|
IsCustomNode,
|
||||||
Theme,
|
LabelRenderer,
|
||||||
} from 'react-base16-styling';
|
ShouldExpandNodeInitially,
|
||||||
import { CircularPropsPassedThroughJSONTree } from './types';
|
} from './types';
|
||||||
|
|
||||||
interface Props extends CircularPropsPassedThroughJSONTree {
|
interface Props extends Partial<CommonExternalProps> {
|
||||||
data: any;
|
data: unknown;
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
invertTheme: boolean;
|
invertTheme?: boolean;
|
||||||
}
|
|
||||||
|
|
||||||
interface State {
|
|
||||||
styling: StylingFunction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const identity = (value: any) => value;
|
const identity = (value: any) => value;
|
||||||
const expandRootNode = (
|
const expandRootNode: ShouldExpandNodeInitially = (keyPath, data, level) =>
|
||||||
keyPath: (string | number)[],
|
level === 0;
|
||||||
data: any,
|
const defaultItemString: GetItemString = (type, data, itemType, itemString) => (
|
||||||
level: number
|
|
||||||
) => level === 0;
|
|
||||||
const defaultItemString = (
|
|
||||||
type: string,
|
|
||||||
data: any,
|
|
||||||
itemType: React.ReactNode,
|
|
||||||
itemString: string
|
|
||||||
) => (
|
|
||||||
<span>
|
<span>
|
||||||
{itemType} {itemString}
|
{itemType} {itemString}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
const defaultLabelRenderer = ([label]: (string | number)[]) => (
|
const defaultLabelRenderer: LabelRenderer = ([label]) => <span>{label}:</span>;
|
||||||
<span>{label}:</span>
|
const noCustomNode: IsCustomNode = () => false;
|
||||||
);
|
|
||||||
const noCustomNode = () => false;
|
|
||||||
|
|
||||||
function checkLegacyTheming(theme: Theme | undefined, props: Props) {
|
export function JSONTree({
|
||||||
const deprecatedStylingMethodsMap = {
|
|
||||||
getArrowStyle: 'arrow',
|
|
||||||
getListStyle: 'nestedNodeChildren',
|
|
||||||
getItemStringStyle: 'nestedNodeItemString',
|
|
||||||
getLabelStyle: 'label',
|
|
||||||
getValueStyle: 'valueText',
|
|
||||||
};
|
|
||||||
|
|
||||||
const deprecatedStylingMethods = Object.keys(
|
|
||||||
deprecatedStylingMethodsMap
|
|
||||||
).filter((name) => props[name as keyof Props]);
|
|
||||||
|
|
||||||
if (deprecatedStylingMethods.length > 0) {
|
|
||||||
if (typeof theme === 'string') {
|
|
||||||
theme = {
|
|
||||||
extend: theme,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
theme = { ...theme };
|
|
||||||
}
|
|
||||||
|
|
||||||
deprecatedStylingMethods.forEach((name) => {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(
|
|
||||||
`Styling method "${name}" is deprecated, use "theme" property instead`
|
|
||||||
);
|
|
||||||
|
|
||||||
(theme as StylingConfig)[
|
|
||||||
deprecatedStylingMethodsMap[
|
|
||||||
name as keyof typeof deprecatedStylingMethodsMap
|
|
||||||
]
|
|
||||||
] = ({ style }, ...args) => ({
|
|
||||||
style: {
|
|
||||||
...style,
|
|
||||||
...props[name as keyof Props](...args),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return theme;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStateFromProps(props: Props) {
|
|
||||||
let theme = checkLegacyTheming(props.theme, props);
|
|
||||||
if (props.invertTheme) {
|
|
||||||
theme = invertTheme(theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
styling: createStylingFromTheme(theme),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class JSONTree extends React.Component<Props, State> {
|
|
||||||
static propTypes = {
|
|
||||||
data: PropTypes.any,
|
|
||||||
hideRoot: PropTypes.bool,
|
|
||||||
theme: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
|
|
||||||
invertTheme: PropTypes.bool,
|
|
||||||
keyPath: PropTypes.arrayOf(
|
|
||||||
PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
|
||||||
),
|
|
||||||
postprocessValue: PropTypes.func,
|
|
||||||
sortObjectKeys: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
shouldExpandNode: expandRootNode,
|
|
||||||
hideRoot: false,
|
|
||||||
keyPath: ['root'],
|
|
||||||
getItemString: defaultItemString,
|
|
||||||
labelRenderer: defaultLabelRenderer,
|
|
||||||
valueRenderer: identity,
|
|
||||||
postprocessValue: identity,
|
|
||||||
isCustomNode: noCustomNode,
|
|
||||||
collectionLimit: 50,
|
|
||||||
invertTheme: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
this.state = getStateFromProps(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps(nextProps: Props) {
|
|
||||||
if (
|
|
||||||
['theme', 'invertTheme'].find(
|
|
||||||
(k) => nextProps[k as keyof Props] !== this.props[k as keyof Props]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
this.setState(getStateFromProps(nextProps));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: Props) {
|
|
||||||
return !!Object.keys(nextProps).find((k) =>
|
|
||||||
k === 'keyPath'
|
|
||||||
? nextProps[k].join('/') !== this.props[k].join('/')
|
|
||||||
: nextProps[k as keyof Props] !== this.props[k as keyof Props]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
data: value,
|
data: value,
|
||||||
keyPath,
|
theme,
|
||||||
postprocessValue,
|
invertTheme: shouldInvertTheme,
|
||||||
hideRoot,
|
keyPath = ['root'],
|
||||||
theme, // eslint-disable-line no-unused-vars
|
labelRenderer = defaultLabelRenderer,
|
||||||
invertTheme: _, // eslint-disable-line no-unused-vars
|
valueRenderer = identity,
|
||||||
...rest
|
shouldExpandNodeInitially = expandRootNode,
|
||||||
} = this.props;
|
hideRoot = false,
|
||||||
|
getItemString = defaultItemString,
|
||||||
const { styling } = this.state;
|
postprocessValue = identity,
|
||||||
|
isCustomNode = noCustomNode,
|
||||||
|
collectionLimit = 50,
|
||||||
|
sortObjectKeys = false,
|
||||||
|
}: Props) {
|
||||||
|
const styling = useMemo(
|
||||||
|
() =>
|
||||||
|
createStylingFromTheme(shouldInvertTheme ? invertTheme(theme) : theme),
|
||||||
|
[theme, shouldInvertTheme]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul {...styling('tree')}>
|
<ul {...styling('tree')}>
|
||||||
<JSONNode
|
<JSONNode
|
||||||
{...{ postprocessValue, hideRoot, styling, ...rest }}
|
|
||||||
keyPath={hideRoot ? [] : keyPath}
|
keyPath={hideRoot ? [] : keyPath}
|
||||||
value={postprocessValue(value)}
|
value={postprocessValue(value)}
|
||||||
|
isCustomNode={isCustomNode}
|
||||||
|
styling={styling}
|
||||||
|
labelRenderer={labelRenderer}
|
||||||
|
valueRenderer={valueRenderer}
|
||||||
|
shouldExpandNodeInitially={shouldExpandNodeInitially}
|
||||||
|
hideRoot={hideRoot}
|
||||||
|
getItemString={getItemString}
|
||||||
|
postprocessValue={postprocessValue}
|
||||||
|
collectionLimit={collectionLimit}
|
||||||
|
sortObjectKeys={sortObjectKeys}
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export { StylingValue };
|
export type {
|
||||||
|
Key,
|
||||||
|
KeyPath,
|
||||||
|
GetItemString,
|
||||||
|
LabelRenderer,
|
||||||
|
ValueRenderer,
|
||||||
|
ShouldExpandNodeInitially,
|
||||||
|
PostprocessValue,
|
||||||
|
IsCustomNode,
|
||||||
|
SortObjectKeys,
|
||||||
|
Styling,
|
||||||
|
CommonExternalProps,
|
||||||
|
} from './types';
|
||||||
|
export type { StylingValue };
|
||||||
|
|
|
@ -1,81 +1,63 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StylingFunction } from 'react-base16-styling';
|
import { StylingFunction } from 'react-base16-styling';
|
||||||
|
|
||||||
interface SharedCircularPropsPassedThroughJSONTree {
|
export type Key = string | number;
|
||||||
keyPath: (string | number)[];
|
|
||||||
labelRenderer: (
|
export type KeyPath = readonly (string | number)[];
|
||||||
keyPath: (string | number)[],
|
|
||||||
|
export type GetItemString = (
|
||||||
|
nodeType: string,
|
||||||
|
data: unknown,
|
||||||
|
itemType: React.ReactNode,
|
||||||
|
itemString: string,
|
||||||
|
keyPath: KeyPath
|
||||||
|
) => React.ReactNode;
|
||||||
|
|
||||||
|
export type LabelRenderer = (
|
||||||
|
keyPath: KeyPath,
|
||||||
nodeType: string,
|
nodeType: string,
|
||||||
expanded: boolean,
|
expanded: boolean,
|
||||||
expandable: boolean
|
expandable: boolean
|
||||||
) => React.ReactNode;
|
) => React.ReactNode;
|
||||||
}
|
|
||||||
interface SharedCircularPropsProvidedByJSONTree
|
|
||||||
extends SharedCircularPropsPassedThroughJSONTree {
|
|
||||||
styling: StylingFunction;
|
|
||||||
}
|
|
||||||
interface JSONValueNodeCircularPropsPassedThroughJSONTree {
|
|
||||||
valueRenderer: (
|
|
||||||
valueAsString: any,
|
|
||||||
value: any,
|
|
||||||
...keyPath: (string | number)[]
|
|
||||||
) => React.ReactNode;
|
|
||||||
}
|
|
||||||
export type JSONValueNodeCircularPropsProvidedByJSONNode =
|
|
||||||
SharedCircularPropsProvidedByJSONTree &
|
|
||||||
JSONValueNodeCircularPropsPassedThroughJSONTree;
|
|
||||||
|
|
||||||
interface JSONNestedNodeCircularPropsPassedThroughJSONTree {
|
export type ValueRenderer = (
|
||||||
shouldExpandNode: (
|
valueAsString: unknown,
|
||||||
keyPath: (string | number)[],
|
value: unknown,
|
||||||
data: any,
|
...keyPath: KeyPath
|
||||||
|
) => React.ReactNode;
|
||||||
|
|
||||||
|
export type ShouldExpandNodeInitially = (
|
||||||
|
keyPath: KeyPath,
|
||||||
|
data: unknown,
|
||||||
level: number
|
level: number
|
||||||
) => boolean;
|
) => boolean;
|
||||||
|
|
||||||
|
export type PostprocessValue = (value: unknown) => unknown;
|
||||||
|
|
||||||
|
export type IsCustomNode = (value: unknown) => boolean;
|
||||||
|
|
||||||
|
export type SortObjectKeys = ((a: unknown, b: unknown) => number) | boolean;
|
||||||
|
|
||||||
|
export type Styling = StylingFunction;
|
||||||
|
|
||||||
|
export type CircularCache = unknown[];
|
||||||
|
|
||||||
|
export interface CommonExternalProps {
|
||||||
|
keyPath: KeyPath;
|
||||||
|
labelRenderer: LabelRenderer;
|
||||||
|
valueRenderer: ValueRenderer;
|
||||||
|
shouldExpandNodeInitially: ShouldExpandNodeInitially;
|
||||||
hideRoot: boolean;
|
hideRoot: boolean;
|
||||||
getItemString: (
|
getItemString: GetItemString;
|
||||||
nodeType: string,
|
postprocessValue: PostprocessValue;
|
||||||
data: any,
|
isCustomNode: IsCustomNode;
|
||||||
itemType: React.ReactNode,
|
|
||||||
itemString: string,
|
|
||||||
keyPath: (string | number)[]
|
|
||||||
) => React.ReactNode;
|
|
||||||
postprocessValue: (value: any) => any;
|
|
||||||
isCustomNode: (value: any) => boolean;
|
|
||||||
collectionLimit: number;
|
collectionLimit: number;
|
||||||
sortObjectKeys?: ((a: any, b: any) => number) | boolean;
|
sortObjectKeys: SortObjectKeys;
|
||||||
}
|
}
|
||||||
export type CircularPropsPassedThroughJSONTree =
|
|
||||||
SharedCircularPropsPassedThroughJSONTree &
|
|
||||||
JSONValueNodeCircularPropsPassedThroughJSONTree &
|
|
||||||
JSONNestedNodeCircularPropsPassedThroughJSONTree;
|
|
||||||
|
|
||||||
interface JSONNestedNodeCircularPropsPassedThroughJSONNode
|
export interface CommonInternalProps extends CommonExternalProps {
|
||||||
extends JSONNestedNodeCircularPropsPassedThroughJSONTree {
|
styling: StylingFunction;
|
||||||
circularCache?: any[];
|
circularCache?: CircularCache;
|
||||||
isCircular?: boolean;
|
|
||||||
level?: number;
|
level?: number;
|
||||||
|
isCircular?: boolean;
|
||||||
}
|
}
|
||||||
export type CircularPropsPassedThroughJSONNode =
|
|
||||||
SharedCircularPropsProvidedByJSONTree &
|
|
||||||
JSONValueNodeCircularPropsPassedThroughJSONTree &
|
|
||||||
JSONNestedNodeCircularPropsPassedThroughJSONNode;
|
|
||||||
|
|
||||||
export interface JSONNestedNodeCircularPropsPassedThroughJSONNestedNode
|
|
||||||
extends JSONNestedNodeCircularPropsPassedThroughJSONNode {
|
|
||||||
circularCache: any[];
|
|
||||||
level: number;
|
|
||||||
}
|
|
||||||
export type CircularPropsPassedThroughJSONNestedNode =
|
|
||||||
SharedCircularPropsProvidedByJSONTree &
|
|
||||||
JSONValueNodeCircularPropsPassedThroughJSONTree &
|
|
||||||
JSONNestedNodeCircularPropsPassedThroughJSONNestedNode;
|
|
||||||
|
|
||||||
export type CircularPropsPassedThroughRenderChildNodes =
|
|
||||||
SharedCircularPropsProvidedByJSONTree &
|
|
||||||
JSONValueNodeCircularPropsPassedThroughJSONTree &
|
|
||||||
JSONNestedNodeCircularPropsPassedThroughJSONNestedNode;
|
|
||||||
|
|
||||||
export type CircularPropsPassedThroughItemRange =
|
|
||||||
SharedCircularPropsProvidedByJSONTree &
|
|
||||||
JSONValueNodeCircularPropsPassedThroughJSONTree &
|
|
||||||
JSONNestedNodeCircularPropsPassedThroughJSONNestedNode;
|
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 2.2.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [b323f77d]
|
||||||
|
- Updated dependencies [b323f77d]
|
||||||
|
- d3-state-visualizer@2.0.0
|
||||||
|
- @redux-devtools/chart-monitor@4.0.0
|
||||||
|
- @redux-devtools/inspector-monitor@3.0.2
|
||||||
|
- @redux-devtools/log-monitor@4.0.2
|
||||||
|
- @redux-devtools/rtk-query-monitor@3.1.1
|
||||||
|
|
||||||
## 2.2.0
|
## 2.2.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
|
@ -6,7 +6,10 @@ module.exports = {
|
||||||
'\\.css$': '<rootDir>/test/__mocks__/styleMock.ts',
|
'\\.css$': '<rootDir>/test/__mocks__/styleMock.ts',
|
||||||
},
|
},
|
||||||
transform: {
|
transform: {
|
||||||
|
'^.+\\.jsx?$': 'babel-jest',
|
||||||
'^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }],
|
'^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }],
|
||||||
},
|
},
|
||||||
resolver: '<rootDir>/jestResolver.js',
|
transformIgnorePatterns: [
|
||||||
|
'node_modules/(?!.pnpm|d3|dateformat|delaunator|internmap|nanoid|robust-predicates|uuid)',
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
module.exports = (path, options) => {
|
|
||||||
return options.defaultResolver(path, {
|
|
||||||
...options,
|
|
||||||
packageFilter: (pkg) => {
|
|
||||||
if (pkg.name === 'nanoid') {
|
|
||||||
pkg.exports['.'].browser = pkg.exports['.'].require;
|
|
||||||
}
|
|
||||||
if (pkg.name === 'uuid' && pkg.version.startsWith('8.')) {
|
|
||||||
delete pkg.exports;
|
|
||||||
delete pkg.module;
|
|
||||||
}
|
|
||||||
return pkg;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@redux-devtools/app",
|
"name": "@redux-devtools/app",
|
||||||
"version": "2.2.0",
|
"version": "2.2.1",
|
||||||
"description": "Redux DevTools app",
|
"description": "Redux DevTools app",
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-app",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-app",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -40,19 +40,19 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@redux-devtools/chart-monitor": "^3.0.0",
|
"@redux-devtools/chart-monitor": "^4.0.0",
|
||||||
"@redux-devtools/core": "^3.13.0",
|
"@redux-devtools/core": "^3.13.0",
|
||||||
"@redux-devtools/inspector-monitor": "^3.0.0",
|
"@redux-devtools/inspector-monitor": "^3.0.2",
|
||||||
"@redux-devtools/inspector-monitor-test-tab": "^1.0.0",
|
"@redux-devtools/inspector-monitor-test-tab": "^1.0.0",
|
||||||
"@redux-devtools/inspector-monitor-trace-tab": "^1.0.0",
|
"@redux-devtools/inspector-monitor-trace-tab": "^1.0.0",
|
||||||
"@redux-devtools/log-monitor": "^4.0.0",
|
"@redux-devtools/log-monitor": "^4.0.2",
|
||||||
"@redux-devtools/rtk-query-monitor": "^3.0.0",
|
"@redux-devtools/rtk-query-monitor": "^3.1.1",
|
||||||
"@redux-devtools/slider-monitor": "^4.0.0",
|
"@redux-devtools/slider-monitor": "^4.0.0",
|
||||||
"@redux-devtools/ui": "^1.3.0",
|
"@redux-devtools/ui": "^1.3.0",
|
||||||
"@reduxjs/toolkit": "^1.9.1",
|
"@reduxjs/toolkit": "^1.9.3",
|
||||||
"@types/prop-types": "^15.7.5",
|
"@types/prop-types": "^15.7.5",
|
||||||
"d3-state-visualizer": "^1.6.0",
|
"d3-state-visualizer": "^2.0.0",
|
||||||
"javascript-stringify": "^2.1.0",
|
"javascript-stringify": "^2.1.0",
|
||||||
"jsan": "^3.1.14",
|
"jsan": "^3.1.14",
|
||||||
"jsondiffpatch": "^0.4.1",
|
"jsondiffpatch": "^0.4.1",
|
||||||
|
@ -63,55 +63,55 @@
|
||||||
"react-icons": "^4.7.1",
|
"react-icons": "^4.7.1",
|
||||||
"react-is": "^18.2.0",
|
"react-is": "^18.2.0",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.0.5",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"socketcluster-client": "^17.1.0"
|
"socketcluster-client": "^17.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@rjsf/core": "^4.2.3",
|
"@rjsf/core": "^4.2.3",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/jsan": "^3.1.2",
|
"@types/jsan": "^3.1.2",
|
||||||
"@types/json-schema": "^7.0.11",
|
"@types/json-schema": "^7.0.11",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.14.4",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/socketcluster-client": "^16.0.0",
|
"@types/socketcluster-client": "^16.0.0",
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
"@types/testing-library__jest-dom": "^5.14.5",
|
"@types/testing-library__jest-dom": "^5.14.5",
|
||||||
"@types/webpack-env": "^1.18.0",
|
"@types/webpack-env": "^1.18.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"babel-loader": "^9.1.0",
|
"babel-loader": "^9.1.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.7.3",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-jest": "^27.1.7",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.14",
|
"fork-ts-checker-webpack-plugin": "^8.0.0",
|
||||||
"html-loader": "^4.2.0",
|
"html-loader": "^4.2.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.3",
|
||||||
"jest-environment-jsdom": "^29.3.1",
|
"jest-environment-jsdom": "^29.4.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"styled-components": "^5.3.6",
|
"styled-components": "^5.3.8",
|
||||||
"ts-jest": "^29.0.3",
|
"ts-jest": "^29.0.5",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "~4.9.4",
|
"typescript": "~4.9.5",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-cli": "^5.0.1",
|
"webpack-cli": "^5.0.1",
|
||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.11.1"
|
||||||
|
@ -120,6 +120,6 @@
|
||||||
"@types/react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
"@types/react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
"react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
"react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
||||||
"styled-components": "^5.3.6"
|
"styled-components": "^5.3.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect, ResolveThunks } from 'react-redux';
|
import { connect, ResolveThunks } from 'react-redux';
|
||||||
import { ChartMonitor } from '@redux-devtools/chart-monitor';
|
import { ChartMonitor } from '@redux-devtools/chart-monitor';
|
||||||
import { NodeWithId } from 'd3-state-visualizer';
|
import type { HierarchyPointNode, Node } from 'd3-state-visualizer';
|
||||||
import { selectMonitorWithState } from '../../actions';
|
import { selectMonitorWithState } from '../../actions';
|
||||||
|
|
||||||
export function getPath(obj: NodeWithId, inspectedStatePath: string[]) {
|
export function getPath(
|
||||||
|
obj: HierarchyPointNode<Node>,
|
||||||
|
inspectedStatePath: string[]
|
||||||
|
) {
|
||||||
const parent = obj.parent;
|
const parent = obj.parent;
|
||||||
if (!parent) return;
|
if (!parent) return;
|
||||||
getPath(parent, inspectedStatePath);
|
getPath(parent, inspectedStatePath);
|
||||||
let name = obj.name;
|
let name = obj.data.name;
|
||||||
const item = /.+\[(\d+)]/.exec(name);
|
const item = /.+\[(\d+)]/.exec(name);
|
||||||
if (item) name = item[1];
|
if (item) name = item[1];
|
||||||
inspectedStatePath.push(name);
|
inspectedStatePath.push(name);
|
||||||
|
@ -20,7 +23,7 @@ type Props = DispatchProps;
|
||||||
class ChartMonitorWrapper extends Component<Props> {
|
class ChartMonitorWrapper extends Component<Props> {
|
||||||
static update = ChartMonitor.update;
|
static update = ChartMonitor.update;
|
||||||
|
|
||||||
onClickText = (data: NodeWithId) => {
|
onClickText = (data: HierarchyPointNode<Node>) => {
|
||||||
const inspectedStatePath: string[] = [];
|
const inspectedStatePath: string[] = [];
|
||||||
getPath(data, inspectedStatePath);
|
getPath(data, inspectedStatePath);
|
||||||
this.props.selectMonitorWithState('InspectorMonitor', {
|
this.props.selectMonitorWithState('InspectorMonitor', {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React, { Component, RefCallback } from 'react';
|
import React, { Component, RefCallback } from 'react';
|
||||||
import { connect, ResolveThunks } from 'react-redux';
|
import { connect, ResolveThunks } from 'react-redux';
|
||||||
import { withTheme } from 'styled-components';
|
import { withTheme } from 'styled-components';
|
||||||
import { InputOptions, NodeWithId, tree } from 'd3-state-visualizer';
|
import { tree } from 'd3-state-visualizer';
|
||||||
|
import type { HierarchyPointNode, Node, Options } from 'd3-state-visualizer';
|
||||||
import { getPath } from '../ChartMonitorWrapper';
|
import { getPath } from '../ChartMonitorWrapper';
|
||||||
import { updateMonitorState } from '../../../actions';
|
import { updateMonitorState } from '../../../actions';
|
||||||
import { ThemeFromProvider } from '@redux-devtools/ui';
|
import { ThemeFromProvider } from '@redux-devtools/ui';
|
||||||
|
@ -54,12 +55,12 @@ class ChartTab extends Component<Props> {
|
||||||
this.renderChart(props.data as {} | null | undefined);
|
this.renderChart(props.data as {} | null | undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
getChartTheme(theme: ThemeFromProvider): Partial<InputOptions> {
|
getChartTheme(theme: ThemeFromProvider): Partial<Options> {
|
||||||
return {
|
return {
|
||||||
heightBetweenNodesCoeff: 1,
|
heightBetweenNodesCoeff: 1,
|
||||||
widthBetweenNodesCoeff: 1.3,
|
widthBetweenNodesCoeff: 1.3,
|
||||||
tooltipOptions: {
|
tooltipOptions: {
|
||||||
style: {
|
styles: {
|
||||||
color: theme.base06,
|
color: theme.base06,
|
||||||
'background-color': theme.base01,
|
'background-color': theme.base01,
|
||||||
opacity: '0.9',
|
opacity: '0.9',
|
||||||
|
@ -69,29 +70,29 @@ class ChartTab extends Component<Props> {
|
||||||
offset: { left: 30, top: 10 },
|
offset: { left: 30, top: 10 },
|
||||||
indentationSize: 2,
|
indentationSize: 2,
|
||||||
},
|
},
|
||||||
style: {
|
chartStyles: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
node: {
|
},
|
||||||
|
nodeStyleOptions: {
|
||||||
colors: {
|
colors: {
|
||||||
default: theme.base0B,
|
default: theme.base0B,
|
||||||
collapsed: theme.base0B,
|
collapsed: theme.base0B,
|
||||||
parent: theme.base0E,
|
parent: theme.base0E,
|
||||||
},
|
},
|
||||||
radius: 7,
|
radius: 7,
|
||||||
} as unknown as string,
|
},
|
||||||
text: {
|
textStyleOptions: {
|
||||||
colors: {
|
colors: {
|
||||||
default: theme.base0D,
|
default: theme.base0D,
|
||||||
hover: theme.base06,
|
hover: theme.base06,
|
||||||
},
|
},
|
||||||
} as unknown as string,
|
|
||||||
},
|
},
|
||||||
onClickText: this.onClickText,
|
onClickText: this.onClickText,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickText = (data: NodeWithId) => {
|
onClickText = (data: HierarchyPointNode<Node>) => {
|
||||||
const inspectedStatePath: string[] = [];
|
const inspectedStatePath: string[] = [];
|
||||||
getPath(data, inspectedStatePath);
|
getPath(data, inspectedStatePath);
|
||||||
this.props.updateMonitorState({
|
this.props.updateMonitorState({
|
||||||
|
|
|
@ -1,5 +1,19 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 4.0.0
|
||||||
|
|
||||||
|
### Major Changes
|
||||||
|
|
||||||
|
- b323f77d: Upgrade D3
|
||||||
|
|
||||||
|
- Split `style` option into `chartStyles`, `nodeStyleOptions`, `textStyleOptions`, and `linkStyles`.
|
||||||
|
- The shape of the argument passed to the `onClickText` option has been updated.
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [b323f77d]
|
||||||
|
- d3-state-visualizer@2.0.0
|
||||||
|
|
||||||
## 3.0.1
|
## 3.0.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
|
@ -48,15 +48,17 @@ Consult the [`DockMonitor` README](https://github.com/reduxjs/redux-devtools/tre
|
||||||
You can read the React component [propTypes](https://github.com/reduxjs/redux-devtools/blob/master/packages/redux-devtools-chart-monitor/src/Chart.js#L11) in addition to the details below:
|
You can read the React component [propTypes](https://github.com/reduxjs/redux-devtools/blob/master/packages/redux-devtools-chart-monitor/src/Chart.js#L11) in addition to the details below:
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `defaultIsVisible` | By default, set to `true`. |
|
| `defaultIsVisible` | By default, set to `true`. |
|
||||||
| `transitionDuration` | By default, set to `750`, in milliseconds. |
|
| `transitionDuration` | By default, set to `750`, in milliseconds. |
|
||||||
| `heightBetweenNodesCoeff` | By default, set to `1`. |
|
| `heightBetweenNodesCoeff` | By default, set to `1`. |
|
||||||
| `widthBetweenNodesCoeff` | By default, set to `1.3`. |
|
| `widthBetweenNodesCoeff` | By default, set to `1.3`. |
|
||||||
| `isSorted` | By default, set to `false`. |
|
| `isSorted` | By default, set to `false`. |
|
||||||
| `style` | {<br> width: '100%', height: '100%', // i.e fullscreen for [`DockMonitor`](https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-dock-monitor)<br> text: {<br> colors: {<br> 'default': `theme.base0D`,<br> hover: `theme.base06`<br> }<br> },<br> node: {<br> colors: {<br> 'default': `theme.base0B`,<br> collapsed: `theme.base0B`,<br> parent: `theme.base0E`<br> },<br> radius: 7<br> }<br>} |
|
| `chartStyles` | {<br> width: '100%', height: '100%', // i.e fullscreen for [`DockMonitor`](https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-dock-monitor)<br>} |
|
||||||
|
| `textStyleOptions` | {<br> colors: {<br> default: `theme.base0D`,<br> hover: `theme.base06`,<br> },<br>} |
|
||||||
|
| `nodeStyleOptions` | {<br> colors: {<br> default: `theme.base0B`,<br> collapsed: `theme.base0B`,<br> parent: `theme.base0E`,<br> },<br> radius: 7,<br>} |
|
||||||
| `onClickText` | Function called with a reference to the clicked node as first argument when clicking on the text next to a node. |
|
| `onClickText` | Function called with a reference to the clicked node as first argument when clicking on the text next to a node. |
|
||||||
| `tooltipOptions` | {<br> disabled: false,<br> indentationSize: 2,<br> style: {<br> 'background-color': `theme.base06`,<br> 'opacity': '0.7',<br> 'border-radius': '5px',<br> 'padding': '5px'<br> }<br>}<br>[More info](https://github.com/reduxjs/redux-devtools/tree/master/packages/d3tooltip#api). |
|
| `tooltipOptions` | {<br> disabled: false,<br> indentationSize: 2,<br> styles: {<br> 'background-color': `theme.base06`,<br> 'opacity': '0.7',<br> 'border-radius': '5px',<br> 'padding': '5px',<br> },<br>}<br>[More info](https://github.com/reduxjs/redux-devtools/tree/master/packages/d3tooltip#api). |
|
||||||
|
|
||||||
#### Redux DevTools props
|
#### Redux DevTools props
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@redux-devtools/chart-monitor",
|
"name": "@redux-devtools/chart-monitor",
|
||||||
"version": "3.0.1",
|
"version": "4.0.0",
|
||||||
"description": "Chart monitor for Redux DevTools",
|
"description": "Chart monitor for Redux DevTools",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"redux",
|
"redux",
|
||||||
|
@ -39,34 +39,32 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint"
|
"prepublish": "pnpm run type-check && pnpm run lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@types/prop-types": "^15.7.5",
|
|
||||||
"@types/redux-devtools-themes": "^1.0.0",
|
"@types/redux-devtools-themes": "^1.0.0",
|
||||||
"d3-state-visualizer": "^1.6.0",
|
"d3-state-visualizer": "^2.0.0",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.3.0",
|
||||||
"prop-types": "^15.8.1",
|
|
||||||
"redux-devtools-themes": "^1.0.0"
|
"redux-devtools-themes": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@redux-devtools/core": "^3.13.1",
|
"@redux-devtools/core": "^3.13.1",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@redux-devtools/core": "^3.13.1",
|
"@redux-devtools/core": "^3.13.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { Component, createRef } from 'react';
|
import React, { Component, createRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { tree } from 'd3-state-visualizer';
|
||||||
import { tree, NodeWithId, Primitive } from 'd3-state-visualizer';
|
import type { Options } from 'd3-state-visualizer';
|
||||||
import { Action, Dispatch } from 'redux';
|
import { Action, Dispatch } from 'redux';
|
||||||
import { LiftedAction, LiftedState } from '@redux-devtools/core';
|
import { LiftedAction, LiftedState } from '@redux-devtools/core';
|
||||||
import * as themes from 'redux-devtools-themes';
|
import * as themes from 'redux-devtools-themes';
|
||||||
|
@ -12,7 +12,8 @@ const wrapperStyle = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Props<S, A extends Action<unknown>>
|
export interface Props<S, A extends Action<unknown>>
|
||||||
extends LiftedState<S, A, ChartMonitorState> {
|
extends LiftedState<S, A, ChartMonitorState>,
|
||||||
|
Options {
|
||||||
dispatch: Dispatch<LiftedAction<S, A, ChartMonitorState>>;
|
dispatch: Dispatch<LiftedAction<S, A, ChartMonitorState>>;
|
||||||
preserveScrollTop: boolean;
|
preserveScrollTop: boolean;
|
||||||
select: (state: S) => unknown;
|
select: (state: S) => unknown;
|
||||||
|
@ -20,76 +21,10 @@ export interface Props<S, A extends Action<unknown>>
|
||||||
invertTheme: boolean;
|
invertTheme: boolean;
|
||||||
|
|
||||||
state: S | null;
|
state: S | null;
|
||||||
isSorted: boolean;
|
|
||||||
heightBetweenNodesCoeff: number;
|
|
||||||
widthBetweenNodesCoeff: number;
|
|
||||||
onClickText: (datum: NodeWithId) => void;
|
|
||||||
tooltipOptions: {
|
|
||||||
disabled: boolean;
|
|
||||||
offset: {
|
|
||||||
left: number;
|
|
||||||
top: number;
|
|
||||||
};
|
|
||||||
indentationSize: number;
|
|
||||||
style: { [key: string]: Primitive } | undefined;
|
|
||||||
};
|
|
||||||
style: { [key: string]: Primitive } | undefined;
|
|
||||||
defaultIsVisible?: boolean;
|
defaultIsVisible?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Chart<S, A extends Action<unknown>> extends Component<Props<S, A>> {
|
class Chart<S, A extends Action<unknown>> extends Component<Props<S, A>> {
|
||||||
static propTypes = {
|
|
||||||
state: PropTypes.object,
|
|
||||||
rootKeyName: PropTypes.string,
|
|
||||||
pushMethod: PropTypes.oneOf(['push', 'unshift']),
|
|
||||||
tree: PropTypes.shape({
|
|
||||||
name: PropTypes.string,
|
|
||||||
children: PropTypes.array,
|
|
||||||
}),
|
|
||||||
id: PropTypes.string,
|
|
||||||
style: PropTypes.shape({
|
|
||||||
node: PropTypes.shape({
|
|
||||||
colors: PropTypes.shape({
|
|
||||||
default: PropTypes.string,
|
|
||||||
parent: PropTypes.string,
|
|
||||||
collapsed: PropTypes.string,
|
|
||||||
}),
|
|
||||||
radius: PropTypes.number,
|
|
||||||
}),
|
|
||||||
text: PropTypes.shape({
|
|
||||||
colors: PropTypes.shape({
|
|
||||||
default: PropTypes.string,
|
|
||||||
hover: PropTypes.string,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
link: PropTypes.object,
|
|
||||||
}),
|
|
||||||
size: PropTypes.number,
|
|
||||||
aspectRatio: PropTypes.number,
|
|
||||||
margin: PropTypes.shape({
|
|
||||||
top: PropTypes.number,
|
|
||||||
right: PropTypes.number,
|
|
||||||
bottom: PropTypes.number,
|
|
||||||
left: PropTypes.number,
|
|
||||||
}),
|
|
||||||
isSorted: PropTypes.bool,
|
|
||||||
heightBetweenNodesCoeff: PropTypes.number,
|
|
||||||
widthBetweenNodesCoeff: PropTypes.number,
|
|
||||||
transitionDuration: PropTypes.number,
|
|
||||||
onClickText: PropTypes.func,
|
|
||||||
tooltipOptions: PropTypes.shape({
|
|
||||||
disabled: PropTypes.bool,
|
|
||||||
left: PropTypes.number,
|
|
||||||
top: PropTypes.number,
|
|
||||||
offset: PropTypes.shape({
|
|
||||||
left: PropTypes.number,
|
|
||||||
top: PropTypes.number,
|
|
||||||
}),
|
|
||||||
indentationSize: PropTypes.number,
|
|
||||||
style: PropTypes.object,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
divRef = createRef<HTMLDivElement>();
|
divRef = createRef<HTMLDivElement>();
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
renderChart?: (state?: {} | null | undefined) => void;
|
renderChart?: (state?: {} | null | undefined) => void;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React, { CSSProperties, PureComponent } from 'react';
|
import React, { CSSProperties, PureComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import * as themes from 'redux-devtools-themes';
|
import * as themes from 'redux-devtools-themes';
|
||||||
import {
|
import {
|
||||||
ActionCreators,
|
ActionCreators,
|
||||||
|
@ -8,7 +7,7 @@ import {
|
||||||
} from '@redux-devtools/core';
|
} from '@redux-devtools/core';
|
||||||
import deepmerge from 'deepmerge';
|
import deepmerge from 'deepmerge';
|
||||||
import { Action, Dispatch } from 'redux';
|
import { Action, Dispatch } from 'redux';
|
||||||
import { NodeWithId, Primitive } from 'd3-state-visualizer';
|
import type { Options } from 'd3-state-visualizer';
|
||||||
|
|
||||||
import reducer, { ChartMonitorState } from './reducers';
|
import reducer, { ChartMonitorState } from './reducers';
|
||||||
import Chart, { Props } from './Chart';
|
import Chart, { Props } from './Chart';
|
||||||
|
@ -41,37 +40,14 @@ function invertColors(theme: themes.Base16Theme) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChartMonitorProps<S, A extends Action<unknown>>
|
export interface ChartMonitorProps<S, A extends Action<unknown>>
|
||||||
extends LiftedState<S, A, ChartMonitorState> {
|
extends LiftedState<S, A, ChartMonitorState>,
|
||||||
|
Options {
|
||||||
dispatch: Dispatch<LiftedAction<S, A, ChartMonitorState>>;
|
dispatch: Dispatch<LiftedAction<S, A, ChartMonitorState>>;
|
||||||
preserveScrollTop: boolean;
|
preserveScrollTop: boolean;
|
||||||
select: (state: S) => unknown;
|
select: (state: S) => unknown;
|
||||||
theme: keyof typeof themes | themes.Base16Theme;
|
theme: keyof typeof themes | themes.Base16Theme;
|
||||||
invertTheme: boolean;
|
invertTheme: boolean;
|
||||||
|
|
||||||
state: S | null;
|
|
||||||
isSorted: boolean;
|
|
||||||
heightBetweenNodesCoeff: number;
|
|
||||||
widthBetweenNodesCoeff: number;
|
|
||||||
onClickText: (datum: NodeWithId) => void;
|
|
||||||
tooltipOptions: unknown;
|
|
||||||
style: {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
node: {
|
|
||||||
colors: {
|
|
||||||
default: string;
|
|
||||||
collapsed: string;
|
|
||||||
parent: string;
|
|
||||||
};
|
|
||||||
radius: number;
|
|
||||||
};
|
|
||||||
text: {
|
|
||||||
colors: {
|
|
||||||
default: string;
|
|
||||||
hover: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
defaultIsVisible?: boolean;
|
defaultIsVisible?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,23 +56,6 @@ class ChartMonitor<S, A extends Action<unknown>> extends PureComponent<
|
||||||
> {
|
> {
|
||||||
static update = reducer;
|
static update = reducer;
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
dispatch: PropTypes.func,
|
|
||||||
computedStates: PropTypes.array,
|
|
||||||
currentStateIndex: PropTypes.number,
|
|
||||||
actionsById: PropTypes.object,
|
|
||||||
stagedActionIds: PropTypes.array,
|
|
||||||
skippedActionIds: PropTypes.array,
|
|
||||||
monitorState: PropTypes.shape({
|
|
||||||
initialScrollTop: PropTypes.number,
|
|
||||||
}),
|
|
||||||
|
|
||||||
preserveScrollTop: PropTypes.bool,
|
|
||||||
select: PropTypes.func.isRequired,
|
|
||||||
theme: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
|
|
||||||
invertTheme: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
select: (state: unknown) => state,
|
select: (state: unknown) => state,
|
||||||
theme: 'nicinabox',
|
theme: 'nicinabox',
|
||||||
|
@ -140,45 +99,10 @@ class ChartMonitor<S, A extends Action<unknown>> extends PureComponent<
|
||||||
return invertTheme ? invertColors(themes.nicinabox) : themes.nicinabox;
|
return invertTheme ? invertColors(themes.nicinabox) : themes.nicinabox;
|
||||||
}
|
}
|
||||||
|
|
||||||
getChartStyle() {
|
|
||||||
const theme = this.getTheme();
|
|
||||||
|
|
||||||
return {
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
node: {
|
|
||||||
colors: {
|
|
||||||
default: theme.base0B,
|
|
||||||
collapsed: theme.base0B,
|
|
||||||
parent: theme.base0E,
|
|
||||||
},
|
|
||||||
radius: 7,
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
colors: {
|
|
||||||
default: theme.base0D,
|
|
||||||
hover: theme.base06,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
getChartOptions(props = this.props): Props<S, A> {
|
getChartOptions(props = this.props): Props<S, A> {
|
||||||
const { computedStates } = props;
|
const { computedStates } = props;
|
||||||
const theme = this.getTheme();
|
const theme = this.getTheme();
|
||||||
|
|
||||||
const tooltipOptions = {
|
|
||||||
disabled: false,
|
|
||||||
offset: { left: 30, top: 10 },
|
|
||||||
indentationSize: 2,
|
|
||||||
style: {
|
|
||||||
'background-color': theme.base06,
|
|
||||||
opacity: '0.7',
|
|
||||||
'border-radius': '5px',
|
|
||||||
padding: '5px',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
state: computedStates.length
|
state: computedStates.length
|
||||||
? computedStates[props.currentStateIndex].state
|
? computedStates[props.currentStateIndex].state
|
||||||
|
@ -186,10 +110,35 @@ class ChartMonitor<S, A extends Action<unknown>> extends PureComponent<
|
||||||
isSorted: false,
|
isSorted: false,
|
||||||
heightBetweenNodesCoeff: 1,
|
heightBetweenNodesCoeff: 1,
|
||||||
widthBetweenNodesCoeff: 1.3,
|
widthBetweenNodesCoeff: 1.3,
|
||||||
tooltipOptions,
|
tooltipOptions: {
|
||||||
style: this.getChartStyle() as unknown as
|
disabled: false,
|
||||||
| { [key: string]: Primitive }
|
offset: { left: 30, top: 10 },
|
||||||
| undefined,
|
indentationSize: 2,
|
||||||
|
styles: {
|
||||||
|
'background-color': theme.base06,
|
||||||
|
opacity: '0.7',
|
||||||
|
'border-radius': '5px',
|
||||||
|
padding: '5px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
chartStyles: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
nodeStyleOptions: {
|
||||||
|
colors: {
|
||||||
|
default: theme.base0B,
|
||||||
|
collapsed: theme.base0B,
|
||||||
|
parent: theme.base0E,
|
||||||
|
},
|
||||||
|
radius: 7,
|
||||||
|
},
|
||||||
|
textStyleOptions: {
|
||||||
|
colors: {
|
||||||
|
default: theme.base0D,
|
||||||
|
hover: theme.base06,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return deepmerge(defaultOptions, props);
|
return deepmerge(defaultOptions, props);
|
||||||
|
@ -198,10 +147,9 @@ class ChartMonitor<S, A extends Action<unknown>> extends PureComponent<
|
||||||
render() {
|
render() {
|
||||||
const theme = this.getTheme();
|
const theme = this.getTheme();
|
||||||
|
|
||||||
const ChartAsAny = Chart as any;
|
|
||||||
return (
|
return (
|
||||||
<div style={{ ...styles.container, backgroundColor: theme.base07 }}>
|
<div style={{ ...styles.container, backgroundColor: theme.base07 }}>
|
||||||
<ChartAsAny {...this.getChartOptions()} />
|
<Chart {...this.getChartOptions()} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 2.0.0
|
||||||
|
|
||||||
|
### Major Changes
|
||||||
|
|
||||||
|
- 7e129988: Convert @redux-devtools/cli to ESM. Please [read this](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) for more info about ESM.
|
||||||
|
Update supported Node versions from `>=14.15.0` to `^14.13.1 || ^16.13.0 || >=18.12.0`.
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- a7729dae: Updates `--open` flag to respect protocol and host when provided
|
||||||
|
|
||||||
## 1.0.7
|
## 1.0.7
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
|
@ -9,7 +9,11 @@ function createWindow() {
|
||||||
height: 600,
|
height: 600,
|
||||||
});
|
});
|
||||||
|
|
||||||
mainWindow.loadURL('http://localhost:' + (argv.port ? argv.port : 8000));
|
const port = argv.port ? argv.port : 8000;
|
||||||
|
const host = argv.host ? argv.host : 'localhost';
|
||||||
|
const protocol = argv.protocol ? argv.protocol : 'http';
|
||||||
|
|
||||||
|
mainWindow.loadURL(protocol + '://' + host + ':' + port);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#! /usr/bin/env node
|
#! /usr/bin/env node
|
||||||
|
|
||||||
require('../dist/bin/redux-devtools.js');
|
import '../dist/bin/redux-devtools.js';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module.exports = {
|
export default {
|
||||||
preset: 'ts-jest',
|
preset: 'ts-jest',
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }],
|
'^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }],
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@redux-devtools/cli",
|
"name": "@redux-devtools/cli",
|
||||||
"version": "1.0.7",
|
"version": "2.0.0",
|
||||||
"description": "CLI for remote debugging with Redux DevTools.",
|
"description": "CLI for remote debugging with Redux DevTools.",
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-cli",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-cli",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
"index.js",
|
"index.js",
|
||||||
"defaultDbOptions.json"
|
"defaultDbOptions.json"
|
||||||
],
|
],
|
||||||
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -37,61 +38,61 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.15.0"
|
"node": "^14.13.1 || ^16.13.0 || >= 18.12.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@apollo/server": "^4.4.0",
|
||||||
"@redux-devtools/app": "^2.1.3",
|
"@redux-devtools/app": "^2.1.3",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"apollo-server-express": "^3.11.1",
|
"body-parser": "^1.20.2",
|
||||||
"body-parser": "^1.20.1",
|
"chalk": "^5.2.0",
|
||||||
"chalk": "^4.1.2",
|
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"cross-spawn": "^7.0.3",
|
"cross-spawn": "^7.0.3",
|
||||||
"electron": "^22.0.0",
|
"electron": "^23.1.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"getport": "^0.1.0",
|
"get-port": "^6.1.2",
|
||||||
"graphql": "^16.6.0",
|
"graphql": "^16.6.0",
|
||||||
"knex": "^2.3.0",
|
"knex": "^2.4.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"minimist": "^1.2.7",
|
"minimist": "^1.2.8",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"open": "^8.4.0",
|
"open": "^8.4.2",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-is": "^18.2.0",
|
"react-is": "^18.2.0",
|
||||||
"semver": "^7.3.8",
|
"semver": "^7.3.8",
|
||||||
"socketcluster-server": "^17.2.0",
|
"socketcluster-server": "^17.3.1",
|
||||||
"sqlite3": "^5.1.4",
|
"sqlite3": "^5.1.4",
|
||||||
"styled-components": "^5.3.6",
|
"styled-components": "^5.3.8",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/body-parser": "^1.19.2",
|
"@types/body-parser": "^1.19.2",
|
||||||
"@types/cors": "^2.8.13",
|
"@types/cors": "^2.8.13",
|
||||||
"@types/cross-spawn": "^6.0.2",
|
"@types/cross-spawn": "^6.0.2",
|
||||||
"@types/express": "^4.17.15",
|
"@types/express": "^4.17.17",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash-es": "^4.17.6",
|
||||||
"@types/minimist": "^1.2.2",
|
"@types/minimist": "^1.2.2",
|
||||||
"@types/morgan": "^1.9.3",
|
"@types/morgan": "^1.9.4",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.14.4",
|
||||||
"@types/semver": "^7.3.13",
|
"@types/semver": "^7.3.13",
|
||||||
"@types/socketcluster-client": "^16.0.0",
|
"@types/socketcluster-client": "^16.0.0",
|
||||||
"@types/socketcluster-server": "^16.1.0",
|
"@types/socketcluster-server": "^17.3.0",
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
"@types/supertest": "^2.0.12",
|
"@types/supertest": "^2.0.12",
|
||||||
"@types/uuid": "^9.0.0",
|
"@types/uuid": "^9.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-jest": "^27.1.7",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.3",
|
||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"socketcluster-client": "^17.1.0",
|
"socketcluster-client": "^17.1.1",
|
||||||
"supertest": "^6.3.3",
|
"supertest": "^6.3.3",
|
||||||
"ts-jest": "^29.0.3",
|
"ts-jest": "^29.0.5",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { Store } from '../store';
|
import type { Store } from '../store.js';
|
||||||
|
|
||||||
export const schema = fs
|
export const schema = fs.readFileSync(
|
||||||
.readFileSync(require.resolve('./schema_def.graphql'))
|
new URL('./schema_def.graphql', import.meta.url),
|
||||||
.toString();
|
'utf8'
|
||||||
|
);
|
||||||
|
|
||||||
export const resolvers = {
|
export const resolvers = {
|
||||||
Query: {
|
Query: {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import { Options } from '../options';
|
import type { Options } from '../options.js';
|
||||||
|
|
||||||
const name = '@redux-devtools/cli';
|
const name = '@redux-devtools/cli';
|
||||||
const startFlag = '/* ' + name + ' start */';
|
const startFlag = '/* ' + name + ' start */';
|
||||||
|
@ -56,7 +56,7 @@ export function inject(
|
||||||
startFlag,
|
startFlag,
|
||||||
' require("' + name + '")(' + JSON.stringify(options) + ')',
|
' require("' + name + '")(' + JSON.stringify(options) + ')',
|
||||||
' .then(_remotedev =>',
|
' .then(_remotedev =>',
|
||||||
' _remotedev.on("ready", () => {',
|
' _remotedev.ready.then(() => {',
|
||||||
' if (!_remotedev.portAlreadyUsed) console.log("-".repeat(80));',
|
' if (!_remotedev.portAlreadyUsed) console.log("-".repeat(80));',
|
||||||
' ' + serverFlag,
|
' ' + serverFlag,
|
||||||
' })',
|
' })',
|
||||||
|
|
|
@ -1,16 +1,30 @@
|
||||||
import open from 'open';
|
import open from 'open';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { createRequire } from 'module';
|
||||||
import spawn from 'cross-spawn';
|
import spawn from 'cross-spawn';
|
||||||
import { Options } from '../options';
|
import type { Options } from '../options.js';
|
||||||
|
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
export default async function openApp(app: true | string, options: Options) {
|
export default async function openApp(app: true | string, options: Options) {
|
||||||
if (app === true || app === 'electron') {
|
if (app === true || app === 'electron') {
|
||||||
try {
|
try {
|
||||||
const port = options.port ? `--port=${options.port}` : '';
|
const port = options.port ? `--port=${options.port}` : '';
|
||||||
|
const host = options.host ? `--host=${options.host}` : '';
|
||||||
|
const protocol = options.protocol ? `--protocol=${options.protocol}` : '';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
spawn.sync(require('electron') as string, [
|
spawn(require('electron') as string, [
|
||||||
path.join(__dirname, '..', '..', 'app'),
|
path.join(
|
||||||
|
path.dirname(fileURLToPath(import.meta.url)),
|
||||||
|
'..',
|
||||||
|
'..',
|
||||||
|
'app'
|
||||||
|
),
|
||||||
port,
|
port,
|
||||||
|
host,
|
||||||
|
protocol,
|
||||||
]);
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
@ -33,7 +47,7 @@ export default async function openApp(app: true | string, options: Options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
await open(
|
await open(
|
||||||
`http://localhost:${options.port}/`,
|
`${options.protocol}://${options.host ?? 'localhost'}:${options.port}/`,
|
||||||
app !== 'browser' ? { app: { name: app } } : undefined
|
app !== 'browser' ? { app: { name: app } } : undefined
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import parseArgs from 'minimist';
|
import parseArgs from 'minimist';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import * as injectServer from './injectServer';
|
import * as injectServer from './injectServer.js';
|
||||||
import getOptions from '../options';
|
import getOptions from '../options.js';
|
||||||
import server from '../index';
|
import server from '../index.js';
|
||||||
import openApp from './openApp';
|
import openApp from './openApp.js';
|
||||||
|
|
||||||
const argv = parseArgs(process.argv.slice(2));
|
const argv = parseArgs(process.argv.slice(2));
|
||||||
|
|
||||||
|
@ -87,10 +87,8 @@ if (argv.injectserver) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
const response = await server(argv);
|
||||||
server(argv).then(async function (r) {
|
|
||||||
if (argv.open && argv.open !== 'false') {
|
if (argv.open && argv.open !== 'false') {
|
||||||
await r.listener('ready').once();
|
await response.ready;
|
||||||
await openApp(argv.open as string, options);
|
await openApp(argv.open as string, options);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
|
@ -1,23 +1,37 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import knexModule, { Knex } from 'knex';
|
import { fileURLToPath } from 'url';
|
||||||
|
import knex from 'knex';
|
||||||
|
import type { Knex } from 'knex';
|
||||||
import { AGServer } from 'socketcluster-server';
|
import { AGServer } from 'socketcluster-server';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
type KnexFunction = <TRecord extends {} = any, TResult = unknown[]>(
|
||||||
|
config: Knex.Config | string
|
||||||
|
) => Knex<TRecord, TResult>;
|
||||||
|
|
||||||
export default function connector(options: AGServer.AGServerOptions) {
|
export default function connector(options: AGServer.AGServerOptions) {
|
||||||
const dbOptions = options.dbOptions as Knex.Config;
|
const dbOptions = options.dbOptions as Knex.Config;
|
||||||
dbOptions.useNullAsDefault = true;
|
dbOptions.useNullAsDefault = true;
|
||||||
if (!(dbOptions as any).migrate) {
|
if (!(dbOptions as any).migrate) {
|
||||||
return knexModule(dbOptions);
|
return (knex as unknown as KnexFunction)(dbOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbOptions.migrations = { directory: path.resolve(__dirname, 'migrations') };
|
dbOptions.migrations = {
|
||||||
dbOptions.seeds = { directory: path.resolve(__dirname, 'seeds') };
|
directory: path.join(
|
||||||
const knex = knexModule(dbOptions);
|
path.dirname(fileURLToPath(import.meta.url)),
|
||||||
|
'migrations'
|
||||||
|
),
|
||||||
|
};
|
||||||
|
dbOptions.seeds = {
|
||||||
|
directory: path.join(path.dirname(fileURLToPath(import.meta.url)), 'seeds'),
|
||||||
|
};
|
||||||
|
const knexInstance = (knex as unknown as KnexFunction)(dbOptions);
|
||||||
|
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
knex.migrate
|
knexInstance.migrate
|
||||||
.latest({ loadExtensions: ['.js'] })
|
.latest({ loadExtensions: ['.js'] })
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return knex.seed.run({ loadExtensions: ['.js'] });
|
return knexInstance.seed.run({ loadExtensions: ['.js'] });
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
console.log(' \x1b[0;32m[Done]\x1b[0m Migrations are finished\n');
|
console.log(' \x1b[0;32m[Done]\x1b[0m Migrations are finished\n');
|
||||||
|
@ -27,5 +41,5 @@ export default function connector(options: AGServer.AGServerOptions) {
|
||||||
});
|
});
|
||||||
/* eslint-enable no-console */
|
/* eslint-enable no-console */
|
||||||
|
|
||||||
return knex;
|
return knexInstance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
declare module 'getport' {
|
|
||||||
export default function getport(
|
|
||||||
start: number,
|
|
||||||
callback: (e: Error | undefined, port: number) => void
|
|
||||||
): void;
|
|
||||||
}
|
|
|
@ -1,23 +1,19 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
import getPort from 'getport';
|
import getPort from 'get-port';
|
||||||
import socketClusterServer from 'socketcluster-server';
|
import socketClusterServer from 'socketcluster-server';
|
||||||
import getOptions, { Options } from './options';
|
import getOptions from './options.js';
|
||||||
import routes from './routes';
|
import routes from './routes.js';
|
||||||
import createStore from './store';
|
import createStore from './store.js';
|
||||||
|
|
||||||
// var LOG_LEVEL_NONE = 0;
|
// const LOG_LEVEL_NONE = 0;
|
||||||
const LOG_LEVEL_ERROR = 1;
|
// const LOG_LEVEL_ERROR = 1;
|
||||||
const LOG_LEVEL_WARN = 2;
|
const LOG_LEVEL_WARN = 2;
|
||||||
const LOG_LEVEL_INFO = 3;
|
const LOG_LEVEL_INFO = 3;
|
||||||
|
|
||||||
export interface ExtendedOptions extends Options {
|
export default async function (argv: { [arg: string]: any }): Promise<{
|
||||||
allowClientPublish: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function (argv: { [arg: string]: any }): Promise<{
|
|
||||||
portAlreadyUsed?: boolean;
|
portAlreadyUsed?: boolean;
|
||||||
listener: (eventName: 'ready') => { once(): Promise<void> };
|
ready: Promise<void>;
|
||||||
}> {
|
}> {
|
||||||
const options = Object.assign(getOptions(argv), {
|
const options = Object.assign(getOptions(argv), {
|
||||||
allowClientPublish: false,
|
allowClientPublish: false,
|
||||||
|
@ -25,31 +21,18 @@ export default function (argv: { [arg: string]: any }): Promise<{
|
||||||
const port = options.port;
|
const port = options.port;
|
||||||
const logLevel =
|
const logLevel =
|
||||||
options.logLevel === undefined ? LOG_LEVEL_INFO : options.logLevel;
|
options.logLevel === undefined ? LOG_LEVEL_INFO : options.logLevel;
|
||||||
return new Promise(function (resolve) {
|
|
||||||
// Check port already used
|
// Check port already used
|
||||||
getPort(port, function (err, p) {
|
const p = await getPort({ port });
|
||||||
/* eslint-disable no-console */
|
|
||||||
if (err) {
|
|
||||||
if (logLevel >= LOG_LEVEL_ERROR) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (port !== p) {
|
if (port !== p) {
|
||||||
if (logLevel >= LOG_LEVEL_WARN) {
|
if (logLevel >= LOG_LEVEL_WARN) {
|
||||||
console.log(`[ReduxDevTools] Server port ${port} is already used.`);
|
console.log(`[ReduxDevTools] Server port ${port} is already used.`);
|
||||||
}
|
}
|
||||||
resolve({
|
|
||||||
portAlreadyUsed: true,
|
|
||||||
listener: function (eventName: 'ready') {
|
|
||||||
return {
|
return {
|
||||||
once() {
|
portAlreadyUsed: true,
|
||||||
return Promise.resolve();
|
ready: Promise.resolve(),
|
||||||
},
|
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (logLevel >= LOG_LEVEL_INFO) {
|
if (logLevel >= LOG_LEVEL_INFO) {
|
||||||
console.log('[ReduxDevTools] Start server...');
|
console.log('[ReduxDevTools] Start server...');
|
||||||
console.log('-'.repeat(80) + '\n');
|
console.log('-'.repeat(80) + '\n');
|
||||||
|
@ -146,10 +129,9 @@ export default function (argv: { [arg: string]: any }): Promise<{
|
||||||
})();
|
})();
|
||||||
|
|
||||||
httpServer.listen(options.port);
|
httpServer.listen(options.port);
|
||||||
// @ts-expect-error Shouldn't there be a 'ready' event?
|
return {
|
||||||
resolve(agServer);
|
ready: (async () => {
|
||||||
}
|
await agServer.listener('ready' as 'error').once();
|
||||||
/* eslint-enable no-console */
|
})(),
|
||||||
});
|
};
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { ApolloServer } from 'apollo-server-express';
|
|
||||||
import { schema, resolvers } from '../api/schema';
|
|
||||||
import { Store } from '../store';
|
|
||||||
|
|
||||||
export default function (store: Store) {
|
|
||||||
return new ApolloServer({
|
|
||||||
typeDefs: schema,
|
|
||||||
resolvers,
|
|
||||||
context: {
|
|
||||||
store: store,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
import path from 'path';
|
import fs from 'fs';
|
||||||
|
|
||||||
interface ProtocolOptions {
|
interface ProtocolOptions {
|
||||||
key: string | undefined;
|
key: string | undefined;
|
||||||
|
@ -31,9 +31,14 @@ export interface Options {
|
||||||
export default function getOptions(argv: { [arg: string]: any }): Options {
|
export default function getOptions(argv: { [arg: string]: any }): Options {
|
||||||
let dbOptions = argv.dbOptions;
|
let dbOptions = argv.dbOptions;
|
||||||
if (typeof dbOptions === 'string') {
|
if (typeof dbOptions === 'string') {
|
||||||
dbOptions = require(path.resolve(process.cwd(), argv.dbOptions as string));
|
dbOptions = JSON.parse(fs.readFileSync(dbOptions, 'utf8'));
|
||||||
} else if (typeof dbOptions === 'undefined') {
|
} else if (typeof dbOptions === 'undefined') {
|
||||||
dbOptions = require('../defaultDbOptions.json');
|
dbOptions = JSON.parse(
|
||||||
|
fs.readFileSync(
|
||||||
|
new URL('../defaultDbOptions.json', import.meta.url),
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { createRequire } from 'module';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import type { Router } from 'express';
|
import type { Router } from 'express';
|
||||||
import morgan from 'morgan';
|
import morgan from 'morgan';
|
||||||
|
@ -6,12 +8,15 @@ import * as http from 'http';
|
||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import { AGServer } from 'socketcluster-server';
|
import { AGServer } from 'socketcluster-server';
|
||||||
import { ApolloServer } from 'apollo-server-express';
|
import { ApolloServer } from '@apollo/server';
|
||||||
import { AddData, ReportBaseFields, Store } from './store';
|
import { expressMiddleware } from '@apollo/server/express4';
|
||||||
import { resolvers, schema } from './api/schema';
|
import type { AddData, ReportBaseFields, Store } from './store.js';
|
||||||
|
import { resolvers, schema } from './api/schema.js';
|
||||||
|
|
||||||
const app = express.Router();
|
const app = express.Router();
|
||||||
|
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
function serveUmdModule(name: string) {
|
function serveUmdModule(name: string) {
|
||||||
app.use(
|
app.use(
|
||||||
express.static(
|
express.static(
|
||||||
|
@ -20,6 +25,10 @@ function serveUmdModule(name: string) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Context {
|
||||||
|
store?: Store;
|
||||||
|
}
|
||||||
|
|
||||||
function routes(
|
function routes(
|
||||||
options: AGServer.AGServerOptions,
|
options: AGServer.AGServerOptions,
|
||||||
store: Store,
|
store: Store,
|
||||||
|
@ -42,19 +51,19 @@ function routes(
|
||||||
else app.use(morgan('combined'));
|
else app.use(morgan('combined'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const server = new ApolloServer({
|
const server = new ApolloServer<Context>({
|
||||||
typeDefs: schema,
|
typeDefs: schema,
|
||||||
resolvers,
|
resolvers,
|
||||||
context: {
|
|
||||||
store: store,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
server
|
server
|
||||||
.start()
|
.start()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
server.applyMiddleware({ app } as {
|
app.use(
|
||||||
app: express.Application;
|
'/graphql',
|
||||||
});
|
cors<cors.CorsRequest>(),
|
||||||
|
bodyParser.json(),
|
||||||
|
expressMiddleware(server, { context: () => Promise.resolve({ store }) })
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error(error); // eslint-disable-line no-console
|
console.error(error); // eslint-disable-line no-console
|
||||||
|
@ -69,7 +78,12 @@ function routes(
|
||||||
res.send(`reduxDevToolsPort = ${options.port}`);
|
res.send(`reduxDevToolsPort = ${options.port}`);
|
||||||
});
|
});
|
||||||
app.get('*', function (req, res) {
|
app.get('*', function (req, res) {
|
||||||
res.sendFile(path.join(__dirname, '../app/index.html'));
|
res.sendFile(
|
||||||
|
path.join(
|
||||||
|
path.dirname(fileURLToPath(import.meta.url)),
|
||||||
|
'../app/index.html'
|
||||||
|
)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(cors({ methods: 'POST' }));
|
app.use(cors({ methods: 'POST' }));
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { v4 as uuidV4 } from 'uuid';
|
import { v4 as uuidV4 } from 'uuid';
|
||||||
import pick from 'lodash/pick';
|
import { pick } from 'lodash-es';
|
||||||
import { AGServer } from 'socketcluster-server';
|
import { AGServer } from 'socketcluster-server';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import connector from './db/connector';
|
import connector from './db/connector.js';
|
||||||
|
|
||||||
const reports = 'remotedev_reports';
|
const reports = 'remotedev_reports';
|
||||||
// var payloads = 'remotedev_payloads';
|
// var payloads = 'remotedev_payloads';
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"extends": "../../tsconfig.base.json",
|
"extends": "../../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "CommonJS",
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
"outDir": "dist"
|
"outDir": "dist"
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
|
|
|
@ -41,33 +41,33 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint"
|
"prepublish": "pnpm run type-check && pnpm run lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@types/prop-types": "^15.7.5",
|
"@types/prop-types": "^15.7.5",
|
||||||
"parse-key": "^0.2.1",
|
"parse-key": "^0.2.1",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react-dock": "^0.6.0"
|
"react-dock": "^0.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@redux-devtools/core": "^3.13.1",
|
"@redux-devtools/core": "^3.13.1",
|
||||||
"@types/parse-key": "^0.2.0",
|
"@types/parse-key": "^0.2.0",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@redux-devtools/core": "^3.13.1",
|
"@redux-devtools/core": "^3.13.1",
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 3.2.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- a0716740: Fix types for other exports from `@redux-devtools/extension`.
|
||||||
|
|
||||||
|
## 3.2.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 07456db4: Propagate store enhancer generic type when using composeWithDevTools
|
||||||
|
|
||||||
## 3.2.3
|
## 3.2.3
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@redux-devtools/extension",
|
"name": "@redux-devtools/extension",
|
||||||
"version": "3.2.3",
|
"version": "3.2.5",
|
||||||
"description": "Wrappers for Redux DevTools Extension.",
|
"description": "Wrappers for Redux DevTools Extension.",
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-extension",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-extension",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -29,23 +29,23 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint"
|
"prepublish": "pnpm run type-check && pnpm run lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"immutable": "^4.1.0"
|
"immutable": "^4.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"redux": "^3.1.0 || ^4.0.0"
|
"redux": "^3.1.0 || ^4.0.0"
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
import { compose, StoreEnhancer } from 'redux';
|
import { compose } from 'redux';
|
||||||
import { Config, EnhancerOptions } from './index';
|
import type { StoreEnhancer } from 'redux';
|
||||||
|
import type {
|
||||||
|
Config,
|
||||||
|
EnhancerOptions,
|
||||||
|
InferComposedStoreExt,
|
||||||
|
ReduxDevtoolsExtensionCompose,
|
||||||
|
} from './index';
|
||||||
|
|
||||||
declare const process: {
|
declare const process: {
|
||||||
env: {
|
env: {
|
||||||
|
@ -9,15 +15,21 @@ declare const process: {
|
||||||
|
|
||||||
function extensionComposeStub(
|
function extensionComposeStub(
|
||||||
config: Config
|
config: Config
|
||||||
): (...funcs: StoreEnhancer[]) => StoreEnhancer;
|
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
function extensionComposeStub(...funcs: StoreEnhancer[]): StoreEnhancer;
|
...funcs: StoreEnhancers
|
||||||
function extensionComposeStub(...funcs: [Config] | StoreEnhancer[]) {
|
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
function extensionComposeStub<
|
||||||
|
StoreEnhancers extends readonly StoreEnhancer<unknown>[]
|
||||||
|
>(
|
||||||
|
...funcs: StoreEnhancers
|
||||||
|
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
function extensionComposeStub(...funcs: [Config] | StoreEnhancer<unknown>[]) {
|
||||||
if (funcs.length === 0) return undefined;
|
if (funcs.length === 0) return undefined;
|
||||||
if (typeof funcs[0] === 'object') return compose;
|
if (typeof funcs[0] === 'object') return compose;
|
||||||
return compose(...(funcs as StoreEnhancer[]));
|
return compose(...(funcs as StoreEnhancer<unknown>[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const composeWithDevTools =
|
export const composeWithDevTools: ReduxDevtoolsExtensionCompose =
|
||||||
process.env.NODE_ENV !== 'production' &&
|
process.env.NODE_ENV !== 'production' &&
|
||||||
typeof window !== 'undefined' &&
|
typeof window !== 'undefined' &&
|
||||||
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Immutable from 'immutable';
|
import type Immutable from 'immutable';
|
||||||
import { Action, ActionCreator, compose, StoreEnhancer } from 'redux';
|
import { compose } from 'redux';
|
||||||
|
import type { Action, ActionCreator, StoreEnhancer } from 'redux';
|
||||||
|
|
||||||
export interface EnhancerOptions {
|
export interface EnhancerOptions {
|
||||||
/**
|
/**
|
||||||
|
@ -227,9 +228,22 @@ interface ReduxDevtoolsExtension {
|
||||||
connect: (preConfig: Config) => ConnectResponse;
|
connect: (preConfig: Config) => ConnectResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type InferComposedStoreExt<StoreEnhancers> = StoreEnhancers extends [
|
||||||
|
infer HeadStoreEnhancer,
|
||||||
|
...infer RestStoreEnhancers
|
||||||
|
]
|
||||||
|
? HeadStoreEnhancer extends StoreEnhancer<infer StoreExt>
|
||||||
|
? StoreExt & InferComposedStoreExt<RestStoreEnhancers>
|
||||||
|
: never
|
||||||
|
: unknown;
|
||||||
|
|
||||||
export interface ReduxDevtoolsExtensionCompose {
|
export interface ReduxDevtoolsExtensionCompose {
|
||||||
(config: Config): (...funcs: StoreEnhancer[]) => StoreEnhancer;
|
(config: Config): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
(...funcs: StoreEnhancer[]): StoreEnhancer;
|
...funcs: StoreEnhancers
|
||||||
|
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
<StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
|
...funcs: StoreEnhancers
|
||||||
|
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -241,12 +255,18 @@ declare global {
|
||||||
|
|
||||||
function extensionComposeStub(
|
function extensionComposeStub(
|
||||||
config: Config
|
config: Config
|
||||||
): (...funcs: StoreEnhancer[]) => StoreEnhancer;
|
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
function extensionComposeStub(...funcs: StoreEnhancer[]): StoreEnhancer;
|
...funcs: StoreEnhancers
|
||||||
function extensionComposeStub(...funcs: [Config] | StoreEnhancer[]) {
|
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
function extensionComposeStub<
|
||||||
|
StoreEnhancers extends readonly StoreEnhancer<unknown>[]
|
||||||
|
>(
|
||||||
|
...funcs: StoreEnhancers
|
||||||
|
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
function extensionComposeStub(...funcs: [Config] | StoreEnhancer<unknown>[]) {
|
||||||
if (funcs.length === 0) return undefined;
|
if (funcs.length === 0) return undefined;
|
||||||
if (typeof funcs[0] === 'object') return compose;
|
if (typeof funcs[0] === 'object') return compose;
|
||||||
return compose(...(funcs as StoreEnhancer[]));
|
return compose(...(funcs as StoreEnhancer<unknown>[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const composeWithDevTools: ReduxDevtoolsExtensionCompose =
|
export const composeWithDevTools: ReduxDevtoolsExtensionCompose =
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import assign from './utils/assign';
|
import assign from './utils/assign';
|
||||||
import {
|
import { compose } from 'redux';
|
||||||
|
import type {
|
||||||
Action,
|
Action,
|
||||||
compose,
|
|
||||||
Dispatch,
|
Dispatch,
|
||||||
PreloadedState,
|
PreloadedState,
|
||||||
Reducer,
|
Reducer,
|
||||||
StoreEnhancer,
|
StoreEnhancer,
|
||||||
} from 'redux';
|
} from 'redux';
|
||||||
import { Config, EnhancerOptions } from './index';
|
import type { Config, EnhancerOptions, InferComposedStoreExt } from './index';
|
||||||
|
|
||||||
function enhancer(options?: EnhancerOptions): StoreEnhancer {
|
function enhancer(options?: EnhancerOptions): StoreEnhancer {
|
||||||
const config: Config = options || {};
|
const config: Config = options || {};
|
||||||
|
@ -40,20 +40,28 @@ function enhancer(options?: EnhancerOptions): StoreEnhancer {
|
||||||
}
|
}
|
||||||
|
|
||||||
function composeWithEnhancer(config?: EnhancerOptions) {
|
function composeWithEnhancer(config?: EnhancerOptions) {
|
||||||
return function (...funcs: StoreEnhancer[]) {
|
return function (...funcs: StoreEnhancer<unknown>[]) {
|
||||||
return compose(compose(...funcs), enhancer(config));
|
return compose(compose(...funcs), enhancer(config));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function composeWithDevTools(
|
export function composeWithDevTools(
|
||||||
config: Config
|
config: Config
|
||||||
): (...funcs: StoreEnhancer[]) => StoreEnhancer;
|
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
export function composeWithDevTools(...funcs: StoreEnhancer[]): StoreEnhancer;
|
...funcs: StoreEnhancers
|
||||||
export function composeWithDevTools(...funcs: [Config] | StoreEnhancer[]) {
|
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
export function composeWithDevTools<
|
||||||
|
StoreEnhancers extends readonly StoreEnhancer<unknown>[]
|
||||||
|
>(
|
||||||
|
...funcs: StoreEnhancers
|
||||||
|
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
export function composeWithDevTools(
|
||||||
|
...funcs: [Config] | StoreEnhancer<unknown>[]
|
||||||
|
) {
|
||||||
if (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__) {
|
if (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__) {
|
||||||
if (funcs.length === 0) return enhancer();
|
if (funcs.length === 0) return enhancer();
|
||||||
if (typeof funcs[0] === 'object') return composeWithEnhancer(funcs[0]);
|
if (typeof funcs[0] === 'object') return composeWithEnhancer(funcs[0]);
|
||||||
return composeWithEnhancer()(...(funcs as StoreEnhancer[]));
|
return composeWithEnhancer()(...(funcs as StoreEnhancer<unknown>[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (funcs.length === 0) return undefined;
|
if (funcs.length === 0) return undefined;
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import { compose, StoreEnhancer } from 'redux';
|
import { compose } from 'redux';
|
||||||
|
import type { StoreEnhancer } from 'redux';
|
||||||
import * as logOnly from './logOnly';
|
import * as logOnly from './logOnly';
|
||||||
import { Config, EnhancerOptions } from './index';
|
import type {
|
||||||
|
Config,
|
||||||
|
EnhancerOptions,
|
||||||
|
InferComposedStoreExt,
|
||||||
|
ReduxDevtoolsExtensionCompose,
|
||||||
|
} from './index';
|
||||||
|
|
||||||
declare const process: {
|
declare const process: {
|
||||||
env: {
|
env: {
|
||||||
|
@ -10,15 +16,21 @@ declare const process: {
|
||||||
|
|
||||||
function extensionComposeStub(
|
function extensionComposeStub(
|
||||||
config: Config
|
config: Config
|
||||||
): (...funcs: StoreEnhancer[]) => StoreEnhancer;
|
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
|
||||||
function extensionComposeStub(...funcs: StoreEnhancer[]): StoreEnhancer;
|
...funcs: StoreEnhancers
|
||||||
function extensionComposeStub(...funcs: [Config] | StoreEnhancer[]) {
|
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
function extensionComposeStub<
|
||||||
|
StoreEnhancers extends readonly StoreEnhancer<unknown>[]
|
||||||
|
>(
|
||||||
|
...funcs: StoreEnhancers
|
||||||
|
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
|
||||||
|
function extensionComposeStub(...funcs: [Config] | StoreEnhancer<unknown>[]) {
|
||||||
if (funcs.length === 0) return undefined;
|
if (funcs.length === 0) return undefined;
|
||||||
if (typeof funcs[0] === 'object') return compose;
|
if (typeof funcs[0] === 'object') return compose;
|
||||||
return compose(...(funcs as StoreEnhancer[]));
|
return compose(...(funcs as StoreEnhancer<unknown>[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const composeWithDevTools =
|
export const composeWithDevTools: ReduxDevtoolsExtensionCompose =
|
||||||
process.env.NODE_ENV === 'production'
|
process.env.NODE_ENV === 'production'
|
||||||
? logOnly.composeWithDevTools
|
? logOnly.composeWithDevTools
|
||||||
: typeof window !== 'undefined' &&
|
: typeof window !== 'undefined' &&
|
||||||
|
|
|
@ -15,43 +15,43 @@
|
||||||
"@redux-devtools/inspector-monitor": "^3.0.0",
|
"@redux-devtools/inspector-monitor": "^3.0.0",
|
||||||
"@redux-devtools/inspector-monitor-test-tab": "^1.0.0",
|
"@redux-devtools/inspector-monitor-test-tab": "^1.0.0",
|
||||||
"@redux-devtools/ui": "^1.3.0",
|
"@redux-devtools/ui": "^1.3.0",
|
||||||
"immutable": "^4.1.0",
|
"immutable": "^4.2.4",
|
||||||
"lodash.shuffle": "^4.2.0",
|
"lodash.shuffle": "^4.2.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-is": "^18.2.0",
|
"react-is": "^18.2.0",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.0.5",
|
||||||
"react-router-dom": "^6.6.0",
|
"react-router-dom": "^6.8.2",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
"styled-components": "^5.3.6"
|
"styled-components": "^5.3.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@types/lodash.shuffle": "^4.2.7",
|
"@types/lodash.shuffle": "^4.2.7",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.14.4",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/redux-logger": "^3.0.9",
|
"@types/redux-logger": "^3.0.9",
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
"@types/webpack-env": "^1.18.0",
|
"@types/webpack-env": "^1.18.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"babel-loader": "^9.1.0",
|
"babel-loader": "^9.1.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.7.3",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.14",
|
"fork-ts-checker-webpack-plugin": "^8.0.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "~4.9.4",
|
"typescript": "~4.9.5",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-cli": "^5.0.1",
|
"webpack-cli": "^5.0.1",
|
||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.11.1"
|
||||||
|
|
|
@ -5,7 +5,8 @@ module.exports = {
|
||||||
'\\.css$': '<rootDir>/test/__mocks__/styleMock.ts',
|
'\\.css$': '<rootDir>/test/__mocks__/styleMock.ts',
|
||||||
},
|
},
|
||||||
transform: {
|
transform: {
|
||||||
|
'^.+\\.jsx?$': 'babel-jest',
|
||||||
'^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }],
|
'^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }],
|
||||||
},
|
},
|
||||||
resolver: '<rootDir>/jestResolver.js',
|
transformIgnorePatterns: ['node_modules/(?!.pnpm|nanoid)'],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
module.exports = (path, options) => {
|
|
||||||
return options.defaultResolver(path, {
|
|
||||||
...options,
|
|
||||||
packageFilter: (pkg) => {
|
|
||||||
if (pkg.name === 'nanoid') {
|
|
||||||
pkg.exports['.'].browser = pkg.exports['.'].require;
|
|
||||||
}
|
|
||||||
return pkg;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -43,7 +43,7 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@redux-devtools/ui": "^1.3.0",
|
"@redux-devtools/ui": "^1.3.0",
|
||||||
"@types/prop-types": "^15.7.5",
|
"@types/prop-types": "^15.7.5",
|
||||||
"es6template": "^1.0.5",
|
"es6template": "^1.0.5",
|
||||||
|
@ -55,37 +55,37 @@
|
||||||
"simple-diff": "^1.6.0"
|
"simple-diff": "^1.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@redux-devtools/core": "^3.13.0",
|
"@redux-devtools/core": "^3.13.0",
|
||||||
"@redux-devtools/inspector-monitor": "^3.0.0",
|
"@redux-devtools/inspector-monitor": "^3.0.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@types/es6template": "^1.0.0",
|
"@types/es6template": "^1.0.1",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/jsan": "^3.1.2",
|
"@types/jsan": "^3.1.2",
|
||||||
"@types/object-path": "^0.11.1",
|
"@types/object-path": "^0.11.1",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/simple-diff": "^1.6.1",
|
"@types/simple-diff": "^1.6.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-jest": "^27.1.7",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.3",
|
||||||
"jest-environment-jsdom": "^29.3.1",
|
"jest-environment-jsdom": "^29.4.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"ts-jest": "^29.0.3",
|
"ts-jest": "^29.0.5",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@redux-devtools/inspector-monitor": "^3.0.0",
|
"@redux-devtools/inspector-monitor": "^3.0.0",
|
||||||
|
@ -93,6 +93,6 @@
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
"react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
"react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
||||||
"redux": "^3.4.0 || ^4.0.0",
|
"redux": "^3.4.0 || ^4.0.0",
|
||||||
"styled-components": "^5.3.6"
|
"styled-components": "^5.3.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.18.6",
|
"@babel/code-frame": "^7.18.6",
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@types/chrome": "^0.0.206",
|
"@types/chrome": "^0.0.218",
|
||||||
"anser": "^2.1.1",
|
"anser": "^2.1.1",
|
||||||
"html-entities": "^2.3.3",
|
"html-entities": "^2.3.3",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
|
@ -40,40 +40,40 @@
|
||||||
"source-map": "^0.5.7"
|
"source-map": "^0.5.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@redux-devtools/core": "^3.13.0",
|
"@redux-devtools/core": "^3.13.0",
|
||||||
"@redux-devtools/inspector-monitor": "^3.0.0",
|
"@redux-devtools/inspector-monitor": "^3.0.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@types/babel__code-frame": "^7.0.3",
|
"@types/babel__code-frame": "^7.0.3",
|
||||||
"@types/html-entities": "^1.3.4",
|
"@types/html-entities": "^1.3.4",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.14.4",
|
||||||
"@types/path-browserify": "^1.0.0",
|
"@types/path-browserify": "^1.0.0",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/redux-devtools-themes": "^1.0.0",
|
"@types/redux-devtools-themes": "^1.0.0",
|
||||||
"@types/source-map": "0.5.2",
|
"@types/source-map": "0.5.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-jest": "^27.1.7",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.3",
|
||||||
"jest-environment-jsdom": "^29.3.1",
|
"jest-environment-jsdom": "^29.4.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-test-renderer": "^18.2.0",
|
"react-test-renderer": "^18.2.0",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"ts-jest": "^29.0.3",
|
"ts-jest": "^29.0.5",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@redux-devtools/inspector-monitor": "^3.0.0",
|
"@redux-devtools/inspector-monitor": "^3.0.0",
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import typescript from 'rollup-plugin-typescript2';
|
|
||||||
import babel from '@rollup/plugin-babel';
|
|
||||||
import nodePolyfills from 'rollup-plugin-node-polyfills';
|
|
||||||
|
|
||||||
const config = [
|
|
||||||
{
|
|
||||||
input: 'src/StackTraceTab.tsx',
|
|
||||||
output: [
|
|
||||||
{
|
|
||||||
file: 'dist/redux-devtools-inspector-monitor-trace-tab.cjs.js',
|
|
||||||
format: 'cjs',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
file: 'dist/redux-devtools-inspector-monitor-trace-tab.esm.js',
|
|
||||||
format: 'esm',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
typescript(),
|
|
||||||
babel({
|
|
||||||
babelHelpers: 'runtime',
|
|
||||||
extensions: ['.ts', '.tsx'],
|
|
||||||
plugins: ['@babel/plugin-transform-runtime'],
|
|
||||||
}),
|
|
||||||
nodePolyfills(),
|
|
||||||
],
|
|
||||||
external: [
|
|
||||||
/@babel\/runtime/,
|
|
||||||
'react',
|
|
||||||
'redux-devtools-themes',
|
|
||||||
'source-map',
|
|
||||||
'@babel/code-frame',
|
|
||||||
'anser',
|
|
||||||
'html-entities',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default config;
|
|
|
@ -1,5 +1,12 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 3.0.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [81926f32]
|
||||||
|
- react-json-tree@0.18.0
|
||||||
|
|
||||||
## 3.0.1
|
## 3.0.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
|
@ -14,40 +14,40 @@
|
||||||
"@redux-devtools/dock-monitor": "^3.0.0",
|
"@redux-devtools/dock-monitor": "^3.0.0",
|
||||||
"@redux-devtools/inspector-monitor": "^3.0.0",
|
"@redux-devtools/inspector-monitor": "^3.0.0",
|
||||||
"base16": "^1.0.0",
|
"base16": "^1.0.0",
|
||||||
"immutable": "^4.1.0",
|
"immutable": "^4.2.4",
|
||||||
"lodash.shuffle": "^4.2.0",
|
"lodash.shuffle": "^4.2.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.7.0",
|
"react-bootstrap": "^2.7.2",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.0.5",
|
||||||
"react-router-dom": "^6.6.0",
|
"react-router-dom": "^6.8.2",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"redux-logger": "^3.0.6"
|
"redux-logger": "^3.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@types/base16": "^1.0.2",
|
"@types/base16": "^1.0.2",
|
||||||
"@types/lodash.shuffle": "^4.2.7",
|
"@types/lodash.shuffle": "^4.2.7",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.14.4",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/redux-logger": "^3.0.9",
|
"@types/redux-logger": "^3.0.9",
|
||||||
"@types/webpack-env": "^1.18.0",
|
"@types/webpack-env": "^1.18.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"babel-loader": "^9.1.0",
|
"babel-loader": "^9.1.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.14",
|
"fork-ts-checker-webpack-plugin": "^8.0.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "~4.9.4",
|
"typescript": "~4.9.5",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-cli": "^5.0.1",
|
"webpack-cli": "^5.0.1",
|
||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.11.1"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@redux-devtools/inspector-monitor",
|
"name": "@redux-devtools/inspector-monitor",
|
||||||
"version": "3.0.1",
|
"version": "3.0.2",
|
||||||
"description": "Redux DevTools Diff Monitor",
|
"description": "Redux DevTools Diff Monitor",
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-inspector-monitor",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-inspector-monitor",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -35,50 +35,50 @@
|
||||||
"prepublish": "pnpm run type-check && pnpm run lint"
|
"prepublish": "pnpm run type-check && pnpm run lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6",
|
"@babel/runtime": "^7.21.0",
|
||||||
"@types/dragula": "^3.7.1",
|
"@types/dragula": "^3.7.1",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/prop-types": "^15.7.5",
|
"@types/prop-types": "^15.7.5",
|
||||||
"dateformat": "^4.6.3",
|
"dateformat": "^5.0.3",
|
||||||
"hex-rgba": "^1.0.2",
|
"hex-rgba": "^1.0.2",
|
||||||
"immutable": "^4.1.0",
|
"immutable": "^4.2.4",
|
||||||
"javascript-stringify": "^2.1.0",
|
"javascript-stringify": "^2.1.0",
|
||||||
"jsondiffpatch": "^0.4.1",
|
"jsondiffpatch": "^0.4.1",
|
||||||
"jss": "^10.9.2",
|
"jss": "^10.10.0",
|
||||||
"jss-preset-default": "^10.9.2",
|
"jss-preset-default": "^10.10.0",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react-base16-styling": "^0.9.1",
|
"react-base16-styling": "^0.9.1",
|
||||||
"react-dragula": "^1.1.17",
|
"react-dragula": "^1.1.17",
|
||||||
"react-json-tree": "^0.17.0",
|
"react-json-tree": "^0.18.0",
|
||||||
"redux-devtools-themes": "^1.0.0"
|
"redux-devtools-themes": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.19.3",
|
"@babel/cli": "^7.21.0",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.21.0",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@redux-devtools/core": "^3.13.1",
|
"@redux-devtools/core": "^3.13.1",
|
||||||
"@types/dateformat": "^3.0.1",
|
"@types/dateformat": "^5.0.0",
|
||||||
"@types/hex-rgba": "^1.0.1",
|
"@types/hex-rgba": "^1.0.1",
|
||||||
"@types/history": "^4.7.11",
|
"@types/history": "^4.7.11",
|
||||||
"@types/lodash.debounce": "^4.0.7",
|
"@types/lodash.debounce": "^4.0.7",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dragula": "^1.1.0",
|
"@types/react-dragula": "^1.1.0",
|
||||||
"@types/redux-devtools-themes": "^1.0.0",
|
"@types/redux-devtools-themes": "^1.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.47.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"eslint": "^8.30.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"typescript": "~4.9.4"
|
"typescript": "~4.9.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@redux-devtools/core": "^3.13.1",
|
"@redux-devtools/core": "^3.13.1",
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
||||||
import { Base16Theme } from 'redux-devtools-themes';
|
import { Base16Theme } from 'redux-devtools-themes';
|
||||||
import { Action } from 'redux';
|
import { Action } from 'redux';
|
||||||
import type { StylingFunction } from 'react-base16-styling';
|
import type { StylingFunction } from 'react-base16-styling';
|
||||||
|
import type { LabelRenderer } from 'react-json-tree';
|
||||||
import { PerformAction } from '@redux-devtools/core';
|
import { PerformAction } from '@redux-devtools/core';
|
||||||
import { Delta } from 'jsondiffpatch';
|
import { Delta } from 'jsondiffpatch';
|
||||||
import { DEFAULT_STATE, DevtoolsInspectorState } from './redux';
|
import { DEFAULT_STATE, DevtoolsInspectorState } from './redux';
|
||||||
|
@ -11,12 +12,7 @@ import StateTab from './tabs/StateTab';
|
||||||
import ActionTab from './tabs/ActionTab';
|
import ActionTab from './tabs/ActionTab';
|
||||||
|
|
||||||
export interface TabComponentProps<S, A extends Action<unknown>> {
|
export interface TabComponentProps<S, A extends Action<unknown>> {
|
||||||
labelRenderer: (
|
labelRenderer: LabelRenderer;
|
||||||
keyPath: (string | number)[],
|
|
||||||
nodeType: string,
|
|
||||||
expanded: boolean,
|
|
||||||
expandable: boolean
|
|
||||||
) => React.ReactNode;
|
|
||||||
styling: StylingFunction;
|
styling: StylingFunction;
|
||||||
computedStates: { state: S; error?: string }[];
|
computedStates: { state: S; error?: string }[];
|
||||||
actions: { [actionId: number]: PerformAction<A> };
|
actions: { [actionId: number]: PerformAction<A> };
|
||||||
|
@ -152,11 +148,7 @@ class ActionPreview<S, A extends Action<unknown>> extends Component<
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
labelRenderer = (
|
labelRenderer: LabelRenderer = ([key, ...rest], nodeType, expanded) => {
|
||||||
[key, ...rest]: (string | number)[],
|
|
||||||
nodeType: string,
|
|
||||||
expanded: boolean
|
|
||||||
) => {
|
|
||||||
const { styling, onInspectPath, inspectedPath } = this.props;
|
const { styling, onInspectPath, inspectedPath } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user