mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-23 06:29:51 +03:00
commit
69ba4917fb
|
@ -1,7 +1,4 @@
|
||||||
{
|
{
|
||||||
"presets": ["@babel/preset-env"],
|
"presets": ["@babel/preset-env", "@babel/preset-typescript"],
|
||||||
"plugins": [
|
"plugins": ["@babel/plugin-proposal-class-properties"]
|
||||||
"@babel/plugin-proposal-class-properties",
|
|
||||||
"@babel/plugin-proposal-export-default-from"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
3
packages/d3-state-visualizer/.eslintignore
Normal file
3
packages/d3-state-visualizer/.eslintignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
examples
|
||||||
|
lib
|
||||||
|
dist
|
21
packages/d3-state-visualizer/.eslintrc.js
Normal file
21
packages/d3-state-visualizer/.eslintrc.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['*.ts'],
|
||||||
|
extends: '../../eslintrc.ts.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['webpack.config.umd.ts'],
|
||||||
|
extends: '../../eslintrc.ts.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.webpack.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -2,8 +2,17 @@
|
||||||
"name": "d3-state-visualizer-tree-example",
|
"name": "d3-state-visualizer-tree-example",
|
||||||
"version": "0.0.2",
|
"version": "0.0.2",
|
||||||
"description": "Visualize your app state as a tree",
|
"description": "Visualize your app state as a tree",
|
||||||
"private": true,
|
"keywords": [
|
||||||
"main": "index.js",
|
"d3",
|
||||||
|
"state",
|
||||||
|
"store",
|
||||||
|
"visualization"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/d3-state-visualizer/examples/tree",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "webpack-dev-server --open"
|
"start": "webpack-dev-server --open"
|
||||||
},
|
},
|
||||||
|
@ -11,25 +20,9 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
|
||||||
"d3",
|
|
||||||
"state",
|
|
||||||
"store",
|
|
||||||
"visualization"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3-state-visualizer": "^1.3.4",
|
"d3-state-visualizer": "^1.3.4",
|
||||||
"map2tree": "^1.4.2"
|
"map2tree": "^1.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"private": true
|
||||||
"@babel/core": "^7.11.1",
|
|
||||||
"babel-loader": "^8.1.0",
|
|
||||||
"webpack": "^4.44.1",
|
|
||||||
"webpack-dev-server": "^3.11.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
var path = require('path');
|
import * as path from 'path';
|
||||||
var webpack = require('webpack');
|
import * as webpack from 'webpack';
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
|
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
|
||||||
devtool: 'eval-source-map',
|
|
||||||
entry: [
|
entry: [
|
||||||
'webpack-dev-server/client?http://localhost:3000',
|
'webpack-dev-server/client?http://localhost:3000',
|
||||||
'webpack/hot/only-dev-server',
|
'webpack/hot/only-dev-server',
|
||||||
|
@ -14,23 +13,24 @@ module.exports = {
|
||||||
filename: 'bundle.js',
|
filename: 'bundle.js',
|
||||||
publicPath: '/static/',
|
publicPath: '/static/',
|
||||||
},
|
},
|
||||||
plugins: [new webpack.HotModuleReplacementPlugin()],
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.js'],
|
|
||||||
},
|
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.(js|ts)$/,
|
||||||
loaders: ['babel-loader'],
|
loaders: 'babel-loader',
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
include: __dirname,
|
include: __dirname,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||||
|
},
|
||||||
|
plugins: [new webpack.HotModuleReplacementPlugin()],
|
||||||
devServer: {
|
devServer: {
|
||||||
historyApiFallback: true,
|
historyApiFallback: true,
|
||||||
hot: true,
|
hot: true,
|
||||||
port: 3000,
|
port: 3000,
|
||||||
},
|
},
|
||||||
|
devtool: 'eval-source-map',
|
||||||
};
|
};
|
|
@ -2,24 +2,6 @@
|
||||||
"name": "d3-state-visualizer",
|
"name": "d3-state-visualizer",
|
||||||
"version": "1.3.4",
|
"version": "1.3.4",
|
||||||
"description": "Visualize your app state with a range of reusable charts",
|
"description": "Visualize your app state with a range of reusable charts",
|
||||||
"main": "lib/index.js",
|
|
||||||
"files": [
|
|
||||||
"dist",
|
|
||||||
"lib",
|
|
||||||
"src"
|
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rimraf lib dist",
|
|
||||||
"build": "babel src --out-dir lib",
|
|
||||||
"build:umd": "webpack src/index.js -o dist/d3-state-visualizer.js --config webpack.config.development.js",
|
|
||||||
"build:umd:min": "webpack src/index.js -o dist/d3-state-visualizer.min.js --config webpack.config.production.js",
|
|
||||||
"prepare": "npm run build",
|
|
||||||
"prepublishOnly": "npm run clean && npm run build && npm run build:umd && npm run build:umd:min"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"d3",
|
"d3",
|
||||||
"state",
|
"state",
|
||||||
|
@ -27,27 +9,46 @@
|
||||||
"tree",
|
"tree",
|
||||||
"visualization"
|
"visualization"
|
||||||
],
|
],
|
||||||
"author": "romseguy",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/d3-state-visualizer",
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"author": "romseguy",
|
||||||
"@babel/cli": "^7.10.5",
|
"files": [
|
||||||
"@babel/core": "^7.11.1",
|
"dist",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
"lib",
|
||||||
"@babel/plugin-proposal-export-default-from": "^7.10.4",
|
"src"
|
||||||
"@babel/preset-env": "^7.11.0",
|
],
|
||||||
"babel-loader": "^8.1.0",
|
"main": "lib/index.js",
|
||||||
"rimraf": "^3.0.2",
|
"types": "lib/index.d.ts",
|
||||||
"webpack": "^4.44.1"
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "npm run build:types && npm run build:js && npm run build:umd && npm run build:umd:min",
|
||||||
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
|
"build:js": "babel src --out-dir lib --extensions \".ts\" --source-maps inline",
|
||||||
|
"build:umd": "webpack --env.production --progress --config webpack.config.umd.ts",
|
||||||
|
"build:umd:min": "webpack --env.production --progress --config webpack.config.umd.ts",
|
||||||
|
"clean": "rimraf lib dist",
|
||||||
|
"lint": "eslint . --ext .ts",
|
||||||
|
"lint:fix": "eslint . --ext .ts --fix",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"type-check:watch": "npm run type-check -- --watch",
|
||||||
|
"preversion": "npm run type-check && npm run lint",
|
||||||
|
"prepublishOnly": "npm run clean && npm run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/d3": "^3.5.43",
|
||||||
"d3": "^3.5.17",
|
"d3": "^3.5.17",
|
||||||
"d3tooltip": "^1.2.3",
|
"d3tooltip": "^1.2.3",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"map2tree": "^1.4.2",
|
"map2tree": "^1.4.2",
|
||||||
"ramda": "^0.27.1"
|
"ramda": "^0.27.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/ramda": "^0.27.17"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export tree from './tree/tree';
|
|
1
packages/d3-state-visualizer/src/charts/index.ts
Normal file
1
packages/d3-state-visualizer/src/charts/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { default as tree } from './tree/tree';
|
|
@ -1,4 +1,4 @@
|
||||||
function sortObject(obj, strict) {
|
function sortObject(obj: unknown, strict?: boolean) {
|
||||||
if (obj instanceof Array) {
|
if (obj instanceof Array) {
|
||||||
let ary;
|
let ary;
|
||||||
if (strict) {
|
if (strict) {
|
||||||
|
@ -10,16 +10,16 @@ function sortObject(obj, strict) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj && typeof obj === 'object') {
|
if (obj && typeof obj === 'object') {
|
||||||
const tObj = {};
|
const tObj: { [key: string]: unknown } = {};
|
||||||
Object.keys(obj)
|
Object.keys(obj)
|
||||||
.sort()
|
.sort()
|
||||||
.forEach((key) => (tObj[key] = sortObject(obj[key])));
|
.forEach((key) => (tObj[key] = sortObject(obj[key as keyof typeof obj])));
|
||||||
return tObj;
|
return tObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function sortAndSerialize(obj) {
|
export default function sortAndSerialize(obj: unknown) {
|
||||||
return JSON.stringify(sortObject(obj, true), undefined, 2);
|
return JSON.stringify(sortObject(obj, true), undefined, 2);
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import d3 from 'd3';
|
import d3, { ZoomEvent, Primitive } from 'd3';
|
||||||
import { isEmpty } from 'ramda';
|
import { isEmpty } from 'ramda';
|
||||||
import map2tree from 'map2tree';
|
import map2tree from 'map2tree';
|
||||||
import deepmerge from 'deepmerge';
|
import deepmerge from 'deepmerge';
|
||||||
|
@ -10,7 +10,102 @@ import {
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import d3tooltip from 'd3tooltip';
|
import d3tooltip from 'd3tooltip';
|
||||||
|
|
||||||
const defaultOptions = {
|
interface InputOptions {
|
||||||
|
// 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: { [key: string]: Primitive };
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultOptions: Options = {
|
||||||
state: undefined,
|
state: undefined,
|
||||||
rootKeyName: 'state',
|
rootKeyName: 'state',
|
||||||
pushMethod: 'push',
|
pushMethod: 'push',
|
||||||
|
@ -50,11 +145,13 @@ const defaultOptions = {
|
||||||
widthBetweenNodesCoeff: 1,
|
widthBetweenNodesCoeff: 1,
|
||||||
transitionDuration: 750,
|
transitionDuration: 750,
|
||||||
blinkDuration: 100,
|
blinkDuration: 100,
|
||||||
onClickText: () => {},
|
onClickText: () => {
|
||||||
|
// noop
|
||||||
|
},
|
||||||
tooltipOptions: {
|
tooltipOptions: {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
left: undefined,
|
left: undefined,
|
||||||
right: undefined,
|
top: undefined,
|
||||||
offset: {
|
offset: {
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
|
@ -63,7 +160,30 @@ const defaultOptions = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function (DOMNode, options = {}) {
|
export interface NodeWithId {
|
||||||
|
name: string;
|
||||||
|
children?: NodeWithId[] | null;
|
||||||
|
_children?: NodeWithId[] | null;
|
||||||
|
value?: unknown;
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
parent?: NodeWithId;
|
||||||
|
depth?: number;
|
||||||
|
x?: number;
|
||||||
|
y?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NodePosition {
|
||||||
|
parentId: string | null | undefined;
|
||||||
|
id: string;
|
||||||
|
x: number | undefined;
|
||||||
|
y: number | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function (
|
||||||
|
DOMNode: HTMLElement,
|
||||||
|
options: Partial<InputOptions> = {}
|
||||||
|
) {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
style,
|
style,
|
||||||
|
@ -82,23 +202,26 @@ export default function (DOMNode, options = {}) {
|
||||||
tree,
|
tree,
|
||||||
tooltipOptions,
|
tooltipOptions,
|
||||||
onClickText,
|
onClickText,
|
||||||
} = deepmerge(defaultOptions, options);
|
} = deepmerge(defaultOptions, options) as 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 = {
|
const attr: { [key: string]: Primitive } = {
|
||||||
id,
|
id,
|
||||||
preserveAspectRatio: 'xMinYMin slice',
|
preserveAspectRatio: 'xMinYMin slice',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!style.width) {
|
if (!((style as unknown) as { [key: string]: Primitive }).width) {
|
||||||
attr.width = fullWidth;
|
attr.width = fullWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!style.width || !style.height) {
|
if (
|
||||||
|
!((style as unknown) as { [key: string]: Primitive }).width ||
|
||||||
|
!((style as unknown) as { [key: string]: Primitive }).height
|
||||||
|
) {
|
||||||
attr.viewBox = `0 0 ${fullWidth} ${fullHeight}`;
|
attr.viewBox = `0 0 ${fullWidth} ${fullHeight}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,11 +230,16 @@ export default function (DOMNode, options = {}) {
|
||||||
const vis = root
|
const vis = root
|
||||||
.append('svg')
|
.append('svg')
|
||||||
.attr(attr)
|
.attr(attr)
|
||||||
.style({ cursor: '-webkit-grab', ...style })
|
.style(({ cursor: '-webkit-grab', ...style } as unknown) as {
|
||||||
|
[key: string]: Primitive;
|
||||||
|
})
|
||||||
.call(
|
.call(
|
||||||
zoom.on('zoom', () => {
|
zoom.on('zoom', () => {
|
||||||
const { translate, scale } = d3.event;
|
const { translate, scale } = d3.event as ZoomEvent;
|
||||||
vis.attr('transform', `translate(${translate})scale(${scale})`);
|
vis.attr(
|
||||||
|
'transform',
|
||||||
|
`translate(${translate.toString()})scale(${scale})`
|
||||||
|
);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.append('g')
|
.append('g')
|
||||||
|
@ -122,18 +250,21 @@ export default function (DOMNode, options = {}) {
|
||||||
});
|
});
|
||||||
|
|
||||||
let layout = d3.layout.tree().size([width, height]);
|
let layout = d3.layout.tree().size([width, height]);
|
||||||
let data;
|
let data: NodeWithId;
|
||||||
|
|
||||||
if (isSorted) {
|
if (isSorted) {
|
||||||
layout.sort((a, b) =>
|
layout.sort((a, b) =>
|
||||||
b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1
|
(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);
|
||||||
// helps animating transitions
|
// helps animating transitions
|
||||||
let previousNodePositionsById = {
|
let previousNodePositionsById: { [nodeId: string]: NodePosition } = {
|
||||||
root: {
|
root: {
|
||||||
id: 'root',
|
id: 'root',
|
||||||
parentId: null,
|
parentId: null,
|
||||||
|
@ -145,10 +276,14 @@ export default function (DOMNode, options = {}) {
|
||||||
// traverses a map with node positions by going through the chain
|
// traverses a map with node positions by going through the chain
|
||||||
// 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(nodePositionsById, nodeId, filter) {
|
function findParentNodePosition(
|
||||||
|
nodePositionsById: { [nodeId: string]: NodePosition },
|
||||||
|
nodeId: string,
|
||||||
|
filter: (nodePosition: NodePosition) => boolean
|
||||||
|
) {
|
||||||
let currentPosition = nodePositionsById[nodeId];
|
let currentPosition = nodePositionsById[nodeId];
|
||||||
while (currentPosition) {
|
while (currentPosition) {
|
||||||
currentPosition = nodePositionsById[currentPosition.parentId];
|
currentPosition = nodePositionsById[currentPosition.parentId!];
|
||||||
if (!currentPosition) {
|
if (!currentPosition) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -160,14 +295,18 @@ export default function (DOMNode, options = {}) {
|
||||||
|
|
||||||
return function renderChart(nextState = tree || state) {
|
return function renderChart(nextState = tree || state) {
|
||||||
data = !tree
|
data = !tree
|
||||||
? map2tree(nextState, { key: rootKeyName, pushMethod })
|
? // eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
: nextState;
|
(map2tree(nextState as {}, {
|
||||||
|
key: rootKeyName,
|
||||||
|
pushMethod,
|
||||||
|
}) as NodeWithId)
|
||||||
|
: (nextState as NodeWithId);
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
let nodeIndex = 0;
|
let nodeIndex = 0;
|
||||||
|
@ -191,13 +330,13 @@ export default function (DOMNode, options = {}) {
|
||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
/*eslint-disable*/
|
|
||||||
update();
|
update();
|
||||||
/*eslint-enable*/
|
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
// path generator for links
|
// path generator for links
|
||||||
const diagonal = d3.svg.diagonal().projection((d) => [d.y, d.x]);
|
const diagonal = d3.svg
|
||||||
|
.diagonal<NodePosition>()
|
||||||
|
.projection((d) => [d.y!, 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));
|
||||||
|
|
||||||
|
@ -206,12 +345,12 @@ export default function (DOMNode, options = {}) {
|
||||||
width,
|
width,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let nodes = layout.nodes(data);
|
const nodes = layout.nodes(data as d3.layout.tree.Node) as NodeWithId[];
|
||||||
let links = layout.links(nodes);
|
const links = layout.links(nodes as d3.layout.tree.Node[]);
|
||||||
|
|
||||||
nodes.forEach(
|
nodes.forEach(
|
||||||
(node) =>
|
(node) =>
|
||||||
(node.y = node.depth * (maxLabelLength * 7 * widthBetweenNodesCoeff))
|
(node.y = node.depth! * (maxLabelLength * 7 * widthBetweenNodesCoeff))
|
||||||
);
|
);
|
||||||
|
|
||||||
const nodePositions = nodes.map((n) => ({
|
const nodePositions = nodes.map((n) => ({
|
||||||
|
@ -220,15 +359,18 @@ export default function (DOMNode, options = {}) {
|
||||||
x: n.x,
|
x: n.x,
|
||||||
y: n.y,
|
y: n.y,
|
||||||
}));
|
}));
|
||||||
const nodePositionsById = {};
|
const nodePositionsById: { [nodeId: string]: NodePosition } = {};
|
||||||
nodePositions.forEach((node) => (nodePositionsById[node.id] = node));
|
nodePositions.forEach((node) => (nodePositionsById[node.id] = node));
|
||||||
|
|
||||||
// process the node selection
|
// process the node selection
|
||||||
let node = vis
|
const node = vis
|
||||||
.selectAll('g.node')
|
.selectAll('g.node')
|
||||||
.property('__oldData__', (d) => d)
|
.property('__oldData__', (d: NodeWithId) => d)
|
||||||
.data(nodes, (d) => d.id || (d.id = ++nodeIndex));
|
.data(
|
||||||
let nodeEnter = node
|
nodes,
|
||||||
|
(d) => d.id || (d.id = (++nodeIndex as unknown) as string)
|
||||||
|
);
|
||||||
|
const nodeEnter = node
|
||||||
.enter()
|
.enter()
|
||||||
.append('g')
|
.append('g')
|
||||||
.attr({
|
.attr({
|
||||||
|
@ -237,29 +379,27 @@ export default function (DOMNode, options = {}) {
|
||||||
const position = findParentNodePosition(
|
const position = findParentNodePosition(
|
||||||
nodePositionsById,
|
nodePositionsById,
|
||||||
d.id,
|
d.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: style.text.colors.default,
|
fill: style.text.colors.default,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
})
|
})
|
||||||
.on({
|
.on('mouseover', function mouseover(this: any) {
|
||||||
mouseover: function mouseover() {
|
d3.select(this).style({
|
||||||
d3.select(this).style({
|
fill: style.text.colors.hover,
|
||||||
fill: style.text.colors.hover,
|
});
|
||||||
});
|
})
|
||||||
},
|
.on('mouseout', function mouseout(this: any) {
|
||||||
mouseout: function mouseout() {
|
d3.select(this).style({
|
||||||
d3.select(this).style({
|
fill: style.text.colors.default,
|
||||||
fill: style.text.colors.default,
|
});
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!tooltipOptions.disabled) {
|
if (!tooltipOptions.disabled) {
|
||||||
|
@ -279,12 +419,10 @@ export default function (DOMNode, options = {}) {
|
||||||
class: 'nodeCircle',
|
class: 'nodeCircle',
|
||||||
r: 0,
|
r: 0,
|
||||||
})
|
})
|
||||||
.on({
|
.on('click', (clickedNode) => {
|
||||||
click: (clickedNode) => {
|
if ((d3.event as Event).defaultPrevented) return;
|
||||||
if (d3.event.defaultPrevented) return;
|
toggleChildren(clickedNode);
|
||||||
toggleChildren(clickedNode);
|
update();
|
||||||
update();
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
nodeEnterInnerGroup
|
nodeEnterInnerGroup
|
||||||
|
@ -299,9 +437,7 @@ export default function (DOMNode, options = {}) {
|
||||||
'fill-opacity': 0,
|
'fill-opacity': 0,
|
||||||
})
|
})
|
||||||
.text((d) => d.name)
|
.text((d) => d.name)
|
||||||
.on({
|
.on('click', onClickText);
|
||||||
click: onClickText,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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);
|
node.select('text').text((d) => d.name);
|
||||||
|
@ -319,11 +455,11 @@ export default function (DOMNode, options = {}) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// transition nodes to their new position
|
// transition nodes to their new position
|
||||||
let nodeUpdate = node
|
const nodeUpdate = node
|
||||||
.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
|
||||||
|
@ -334,7 +470,7 @@ export default function (DOMNode, options = {}) {
|
||||||
.select('text')
|
.select('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.children || d._children ? -1 : 1) *
|
||||||
(this.getBBox().width / 2 + style.node.radius + 5);
|
(this.getBBox().width / 2 + style.node.radius + 5);
|
||||||
|
@ -344,7 +480,7 @@ export default function (DOMNode, options = {}) {
|
||||||
|
|
||||||
// blink updated nodes
|
// blink updated nodes
|
||||||
node
|
node
|
||||||
.filter(function flick(d) {
|
.filter(function flick(this: any, 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,
|
||||||
|
@ -358,7 +494,7 @@ export default function (DOMNode, options = {}) {
|
||||||
.style('opacity', '1');
|
.style('opacity', '1');
|
||||||
|
|
||||||
// transition exiting nodes to the parent's new position
|
// transition exiting nodes to the parent's new position
|
||||||
let nodeExit = node
|
const nodeExit = node
|
||||||
.exit()
|
.exit()
|
||||||
.transition()
|
.transition()
|
||||||
.duration(transitionDuration)
|
.duration(transitionDuration)
|
||||||
|
@ -367,12 +503,12 @@ export default function (DOMNode, options = {}) {
|
||||||
const position = findParentNodePosition(
|
const position = findParentNodePosition(
|
||||||
previousNodePositionsById,
|
previousNodePositionsById,
|
||||||
d.id,
|
d.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();
|
||||||
|
@ -382,7 +518,9 @@ export default function (DOMNode, options = {}) {
|
||||||
nodeExit.select('text').style('fill-opacity', 0);
|
nodeExit.select('text').style('fill-opacity', 0);
|
||||||
|
|
||||||
// update the links
|
// update the links
|
||||||
let link = vis.selectAll('path.link').data(links, (d) => d.target.id);
|
const link = vis
|
||||||
|
.selectAll('path.link')
|
||||||
|
.data(links, (d) => (d.target as NodeWithId).id);
|
||||||
|
|
||||||
// enter any new links at the parent's previous position
|
// enter any new links at the parent's previous position
|
||||||
link
|
link
|
||||||
|
@ -393,8 +531,8 @@ export default function (DOMNode, options = {}) {
|
||||||
d: (d) => {
|
d: (d) => {
|
||||||
const position = findParentNodePosition(
|
const position = findParentNodePosition(
|
||||||
nodePositionsById,
|
nodePositionsById,
|
||||||
d.target.id,
|
(d.target as NodeWithId).id,
|
||||||
(n) => previousNodePositionsById[n.id]
|
(n) => !!previousNodePositionsById[n.id]
|
||||||
);
|
);
|
||||||
const previousPosition =
|
const previousPosition =
|
||||||
(position && previousNodePositionsById[position.id]) ||
|
(position && previousNodePositionsById[position.id]) ||
|
||||||
|
@ -402,15 +540,18 @@ export default function (DOMNode, options = {}) {
|
||||||
return diagonal({
|
return diagonal({
|
||||||
source: previousPosition,
|
source: previousPosition,
|
||||||
target: previousPosition,
|
target: previousPosition,
|
||||||
});
|
} as d3.svg.diagonal.Link<NodePosition>);
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.style(style.link);
|
.style(style.link);
|
||||||
|
|
||||||
// transition links to their new position
|
// transition links to their new position
|
||||||
link.transition().duration(transitionDuration).attr({
|
link
|
||||||
d: diagonal,
|
.transition()
|
||||||
});
|
.duration(transitionDuration)
|
||||||
|
.attr({
|
||||||
|
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
|
||||||
|
@ -421,8 +562,8 @@ export default function (DOMNode, options = {}) {
|
||||||
d: (d) => {
|
d: (d) => {
|
||||||
const position = findParentNodePosition(
|
const position = findParentNodePosition(
|
||||||
previousNodePositionsById,
|
previousNodePositionsById,
|
||||||
d.target.id,
|
(d.target as NodeWithId).id,
|
||||||
(n) => nodePositionsById[n.id]
|
(n) => !!nodePositionsById[n.id]
|
||||||
);
|
);
|
||||||
const futurePosition =
|
const futurePosition =
|
||||||
(position && nodePositionsById[position.id]) ||
|
(position && nodePositionsById[position.id]) ||
|
|
@ -1,7 +1,8 @@
|
||||||
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';
|
||||||
|
|
||||||
export function collapseChildren(node) {
|
export function collapseChildren(node: NodeWithId) {
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
node._children = node.children;
|
node._children = node.children;
|
||||||
node._children.forEach(collapseChildren);
|
node._children.forEach(collapseChildren);
|
||||||
|
@ -9,7 +10,7 @@ export function collapseChildren(node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function expandChildren(node) {
|
export function expandChildren(node: NodeWithId) {
|
||||||
if (node._children) {
|
if (node._children) {
|
||||||
node.children = node._children;
|
node.children = node._children;
|
||||||
node.children.forEach(expandChildren);
|
node.children.forEach(expandChildren);
|
||||||
|
@ -17,7 +18,7 @@ export function expandChildren(node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggleChildren(node) {
|
export function toggleChildren(node: NodeWithId) {
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
node._children = node.children;
|
node._children = node.children;
|
||||||
node.children = null;
|
node.children = null;
|
||||||
|
@ -28,16 +29,20 @@ export function toggleChildren(node) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function visit(parent, visitFn, childrenFn) {
|
export function visit(
|
||||||
|
parent: NodeWithId,
|
||||||
|
visitFn: (parent: NodeWithId) => void,
|
||||||
|
childrenFn: (parent: NodeWithId) => NodeWithId[] | null | undefined
|
||||||
|
) {
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
visitFn(parent);
|
visitFn(parent);
|
||||||
|
|
||||||
let children = childrenFn(parent);
|
const children = childrenFn(parent);
|
||||||
if (children) {
|
if (children) {
|
||||||
let count = children.length;
|
const count = children.length;
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
visit(children[i], visitFn, childrenFn);
|
visit(children[i], visitFn, childrenFn);
|
||||||
|
@ -45,10 +50,10 @@ export function visit(parent, visitFn, childrenFn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNodeGroupByDepthCount(rootNode) {
|
export function getNodeGroupByDepthCount(rootNode: NodeWithId) {
|
||||||
let nodeGroupByDepthCount = [1];
|
const nodeGroupByDepthCount = [1];
|
||||||
|
|
||||||
const traverseFrom = function traverseFrom(node, depth = 0) {
|
const traverseFrom = function traverseFrom(node: NodeWithId, depth = 0) {
|
||||||
if (!node.children || node.children.length === 0) {
|
if (!node.children || node.children.length === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +73,11 @@ export function getNodeGroupByDepthCount(rootNode) {
|
||||||
return nodeGroupByDepthCount;
|
return nodeGroupByDepthCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTooltipString(node, i, { indentationSize = 4 }) {
|
export function getTooltipString(
|
||||||
|
node: unknown,
|
||||||
|
i: number | undefined,
|
||||||
|
{ indentationSize = 4 }
|
||||||
|
) {
|
||||||
if (!is(Object, node)) return '';
|
if (!is(Object, node)) return '';
|
||||||
|
|
||||||
const spacer = join(' ');
|
const spacer = join(' ');
|
||||||
|
@ -76,10 +85,13 @@ export function getTooltipString(node, i, { indentationSize = 4 }) {
|
||||||
const spaces2nbsp = replace(/\s{2}/g, spacer(new Array(indentationSize)));
|
const spaces2nbsp = replace(/\s{2}/g, spacer(new Array(indentationSize)));
|
||||||
const json2html = pipe(sortAndSerialize, cr2br, spaces2nbsp);
|
const json2html = pipe(sortAndSerialize, cr2br, spaces2nbsp);
|
||||||
|
|
||||||
const children = node.children || node._children;
|
const children = (node as any).children || (node as any)._children;
|
||||||
|
|
||||||
if (typeof node.value !== 'undefined') return json2html(node.value);
|
if (typeof (node as any).value !== 'undefined')
|
||||||
if (typeof node.object !== 'undefined') return json2html(node.object);
|
return json2html((node as any).value);
|
||||||
if (children && children.length) return 'childrenCount: ' + children.length;
|
if (typeof (node as any).object !== 'undefined')
|
||||||
|
return json2html((node as any).object);
|
||||||
|
if (children && children.length)
|
||||||
|
return `childrenCount: ${(children as unknown[]).length}`;
|
||||||
return 'empty';
|
return 'empty';
|
||||||
}
|
}
|
7
packages/d3-state-visualizer/tsconfig.json
Normal file
7
packages/d3-state-visualizer/tsconfig.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.react.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "lib"
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
4
packages/d3-state-visualizer/tsconfig.webpack.json
Normal file
4
packages/d3-state-visualizer/tsconfig.webpack.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"include": ["webpack.config.umd.ts"]
|
||||||
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{ test: /\.js$/, loaders: ['babel-loader'], exclude: /node_modules/ },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
library: 'd3-state-visualizer',
|
|
||||||
libraryExport: 'default',
|
|
||||||
libraryTarget: 'umd',
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.js'],
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,14 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var webpack = require('webpack');
|
|
||||||
var baseConfig = require('./webpack.config.base');
|
|
||||||
|
|
||||||
var config = Object.assign({}, baseConfig);
|
|
||||||
config.mode = 'development';
|
|
||||||
config.plugins = [
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env.NODE_ENV': JSON.stringify('development'),
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
module.exports = config;
|
|
|
@ -1,14 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var webpack = require('webpack');
|
|
||||||
var baseConfig = require('./webpack.config.base');
|
|
||||||
|
|
||||||
var config = Object.assign({}, baseConfig);
|
|
||||||
config.mode = 'production';
|
|
||||||
config.plugins = [
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
module.exports = config;
|
|
28
packages/d3-state-visualizer/webpack.config.umd.ts
Normal file
28
packages/d3-state-visualizer/webpack.config.umd.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export default (env: { production?: boolean } = {}) => ({
|
||||||
|
mode: env.production ? 'production' : 'development',
|
||||||
|
entry: {
|
||||||
|
app: ['./src/index'],
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
library: 'd3-state-visualizer',
|
||||||
|
libraryTarget: 'umd',
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
filename: env.production
|
||||||
|
? 'd3-state-visualizer.min.js'
|
||||||
|
: 'd3-state-visualizer.js',
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(js|ts)$/,
|
||||||
|
loader: 'babel-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"presets": ["@babel/preset-env"]
|
"presets": ["@babel/preset-env", "@babel/preset-typescript"],
|
||||||
|
"plugins": ["@babel/plugin-proposal-class-properties"]
|
||||||
}
|
}
|
||||||
|
|
3
packages/d3tooltip/.eslintignore
Normal file
3
packages/d3tooltip/.eslintignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
examples
|
||||||
|
lib
|
||||||
|
dist
|
21
packages/d3tooltip/.eslintrc.js
Normal file
21
packages/d3tooltip/.eslintrc.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['*.ts'],
|
||||||
|
extends: '../../eslintrc.ts.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['webpack.config.umd.ts'],
|
||||||
|
extends: '../../eslintrc.ts.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.webpack.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -2,46 +2,49 @@
|
||||||
"name": "d3tooltip",
|
"name": "d3tooltip",
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"description": "A highly configurable tooltip for d3",
|
"description": "A highly configurable tooltip for d3",
|
||||||
"main": "lib/index.js",
|
"keywords": [
|
||||||
"scripts": {
|
"d3",
|
||||||
"clean": "rimraf lib dist",
|
"tooltip"
|
||||||
"build": "babel src --out-dir lib",
|
],
|
||||||
"build:umd": "webpack --progress --config webpack.config.umd.js",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/d3tooltip",
|
||||||
"build:umd:min": "webpack --env.production --progress --config webpack.config.umd.js",
|
"bugs": {
|
||||||
"version": "npm run build",
|
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
||||||
"postversion": "git push && git push --tags && npm run clean",
|
|
||||||
"prepare": "npm run clean && npm run build",
|
|
||||||
"prepublishOnly": "npm run clean && npm run build && npm run build:umd && npm run build:umd:min"
|
|
||||||
},
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"author": "romseguy",
|
||||||
"files": [
|
"files": [
|
||||||
"lib",
|
"lib",
|
||||||
"dist",
|
"dist",
|
||||||
"src"
|
"src"
|
||||||
],
|
],
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"types": "lib/index.d.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"scripts": {
|
||||||
"d3",
|
"build": "npm run build:types && npm run build:js && npm run build:umd && npm run build:umd:min",
|
||||||
"tooltip"
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
],
|
"build:js": "babel src --out-dir lib --extensions \".ts\" --source-maps inline",
|
||||||
"author": "romseguy",
|
"build:umd": "webpack --progress --config webpack.config.umd.ts",
|
||||||
"license": "MIT",
|
"build:umd:min": "webpack --env.production --progress --config webpack.config.umd.ts",
|
||||||
"bugs": {
|
"clean": "rimraf lib dist",
|
||||||
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
"lint": "eslint . --ext .ts",
|
||||||
},
|
"lint:fix": "eslint . --ext .ts --fix",
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools",
|
"type-check": "tsc --noEmit",
|
||||||
"devDependencies": {
|
"type-check:watch": "npm run type-check -- --watch",
|
||||||
"@babel/cli": "^7.10.5",
|
"preversion": "npm run type-check && npm run lint",
|
||||||
"@babel/core": "^7.11.1",
|
"prepublishOnly": "npm run clean && npm run build"
|
||||||
"@babel/preset-env": "^7.11.0",
|
|
||||||
"babel-loader": "^8.1.0",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"webpack": "^4.44.1",
|
|
||||||
"webpack-cli": "^3.3.12"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ramda": "^0.27.1"
|
"ramda": "^0.27.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/ramda": "^0.27.17"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/d3": "^3.5.43",
|
||||||
|
"d3": "^3.5.17"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
78
packages/d3tooltip/src/index.js
vendored
78
packages/d3tooltip/src/index.js
vendored
|
@ -1,78 +0,0 @@
|
||||||
import { is } from 'ramda';
|
|
||||||
import utils from './utils';
|
|
||||||
const { prependClass, functor } = utils.default || utils;
|
|
||||||
|
|
||||||
const defaultOptions = {
|
|
||||||
left: undefined, // mouseX
|
|
||||||
top: undefined, // mouseY
|
|
||||||
offset: { left: 0, top: 0 },
|
|
||||||
root: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function tooltip(d3, className = 'tooltip', options = {}) {
|
|
||||||
const { left, top, offset, root } = { ...defaultOptions, ...options };
|
|
||||||
|
|
||||||
let attrs = { class: className };
|
|
||||||
let text = () => '';
|
|
||||||
let styles = {};
|
|
||||||
|
|
||||||
let el;
|
|
||||||
const anchor = root || d3.select('body');
|
|
||||||
const rootNode = anchor.node();
|
|
||||||
|
|
||||||
function tip(selection) {
|
|
||||||
selection.on({
|
|
||||||
'mouseover.tip': (node) => {
|
|
||||||
let [mouseX, mouseY] = d3.mouse(rootNode);
|
|
||||||
let [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
|
|
||||||
|
|
||||||
anchor.selectAll(`div.${className}`).remove();
|
|
||||||
|
|
||||||
el = anchor
|
|
||||||
.append('div')
|
|
||||||
.attr(prependClass(className)(attrs))
|
|
||||||
.style({
|
|
||||||
position: 'absolute',
|
|
||||||
'z-index': 1001,
|
|
||||||
left: x + 'px',
|
|
||||||
top: y + 'px',
|
|
||||||
...styles,
|
|
||||||
})
|
|
||||||
.html(() => text(node));
|
|
||||||
},
|
|
||||||
|
|
||||||
'mousemove.tip': (node) => {
|
|
||||||
let [mouseX, mouseY] = d3.mouse(rootNode);
|
|
||||||
let [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
|
|
||||||
|
|
||||||
el.style({
|
|
||||||
left: x + 'px',
|
|
||||||
top: y + 'px',
|
|
||||||
}).html(() => text(node));
|
|
||||||
},
|
|
||||||
|
|
||||||
'mouseout.tip': () => el.remove(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
tip.attr = function setAttr(d) {
|
|
||||||
if (is(Object, d)) {
|
|
||||||
attrs = { ...attrs, ...d };
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
tip.style = function setStyle(d) {
|
|
||||||
if (is(Object, d)) {
|
|
||||||
styles = { ...styles, ...d };
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
tip.text = function setText(d) {
|
|
||||||
text = functor(d);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
return tip;
|
|
||||||
}
|
|
128
packages/d3tooltip/src/index.ts
Normal file
128
packages/d3tooltip/src/index.ts
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
import d3Package, { Primitive, Selection } from 'd3';
|
||||||
|
import { is } from 'ramda';
|
||||||
|
import utils from './utils';
|
||||||
|
const { prependClass, functor } = utils;
|
||||||
|
|
||||||
|
interface Options<Datum> {
|
||||||
|
left: number | undefined;
|
||||||
|
top: number | undefined;
|
||||||
|
offset: {
|
||||||
|
left: number;
|
||||||
|
top: number;
|
||||||
|
};
|
||||||
|
root: Selection<Datum> | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultOptions: Options<unknown> = {
|
||||||
|
left: undefined, // mouseX
|
||||||
|
top: undefined, // mouseY
|
||||||
|
offset: { left: 0, top: 0 },
|
||||||
|
root: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function tooltip<Datum>(
|
||||||
|
d3: typeof d3Package,
|
||||||
|
className = 'tooltip',
|
||||||
|
options: Partial<Options<Datum>> = {}
|
||||||
|
) {
|
||||||
|
const { left, top, offset, root } = {
|
||||||
|
...defaultOptions,
|
||||||
|
...options,
|
||||||
|
} as Options<Datum>;
|
||||||
|
|
||||||
|
let attrs = { class: className };
|
||||||
|
let text: (datum: Datum, index?: number, outerIndex?: number) => string = (
|
||||||
|
node: Datum
|
||||||
|
) => '';
|
||||||
|
let styles = {};
|
||||||
|
|
||||||
|
let el: Selection<Datum>;
|
||||||
|
const anchor = root || d3.select('body');
|
||||||
|
const rootNode = anchor.node();
|
||||||
|
|
||||||
|
function tip(selection: Selection<Datum>) {
|
||||||
|
selection.on('mouseover.tip', (node) => {
|
||||||
|
const [mouseX, mouseY] = d3.mouse(rootNode);
|
||||||
|
const [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
|
||||||
|
|
||||||
|
anchor.selectAll(`div.${className}`).remove();
|
||||||
|
|
||||||
|
el = anchor
|
||||||
|
.append('div')
|
||||||
|
.attr(prependClass(className)(attrs))
|
||||||
|
.style({
|
||||||
|
position: 'absolute',
|
||||||
|
'z-index': 1001,
|
||||||
|
left: `${x}px`,
|
||||||
|
top: `${y}px`,
|
||||||
|
...styles,
|
||||||
|
})
|
||||||
|
.html(() => text(node)) as Selection<Datum>;
|
||||||
|
});
|
||||||
|
|
||||||
|
selection.on('mousemove.tip', (node) => {
|
||||||
|
const [mouseX, mouseY] = d3.mouse(rootNode);
|
||||||
|
const [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
|
||||||
|
|
||||||
|
el.style({
|
||||||
|
left: `${x}px`,
|
||||||
|
top: `${y}px`,
|
||||||
|
}).html(() => text(node));
|
||||||
|
});
|
||||||
|
|
||||||
|
selection.on('mouseout.tip', () => el.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
tip.attr = function setAttr(
|
||||||
|
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(
|
||||||
|
d:
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
[key: string]:
|
||||||
|
| Primitive
|
||||||
|
| ((datum: Datum, index: number, outerIndex: number) => Primitive);
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
if (is(Object, d)) {
|
||||||
|
styles = {
|
||||||
|
...styles,
|
||||||
|
...(d as {
|
||||||
|
[key: string]:
|
||||||
|
| Primitive
|
||||||
|
| ((datum: Datum, index: number, outerIndex: number) => Primitive);
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
tip.text = function setText(
|
||||||
|
d: string | ((datum: Datum, index?: number, outerIndex?: number) => string)
|
||||||
|
) {
|
||||||
|
text = functor(d);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
return tip;
|
||||||
|
}
|
5
packages/d3tooltip/src/utils/functor.js
vendored
5
packages/d3tooltip/src/utils/functor.js
vendored
|
@ -1,5 +0,0 @@
|
||||||
import { is } from 'ramda';
|
|
||||||
|
|
||||||
export default function functor(v) {
|
|
||||||
return is(Function, v) ? v : () => v;
|
|
||||||
}
|
|
20
packages/d3tooltip/src/utils/functor.ts
Normal file
20
packages/d3tooltip/src/utils/functor.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
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 as Primitive;
|
||||||
|
}
|
20
packages/d3tooltip/src/utils/prependClass.js
vendored
20
packages/d3tooltip/src/utils/prependClass.js
vendored
|
@ -1,20 +0,0 @@
|
||||||
import { mapObjIndexed, join } from 'ramda';
|
|
||||||
import functor from './functor';
|
|
||||||
|
|
||||||
export default function prependClass(className) {
|
|
||||||
return mapObjIndexed((value, key) => {
|
|
||||||
if (key === 'class') {
|
|
||||||
const fn = functor(value);
|
|
||||||
|
|
||||||
return (d, i) => {
|
|
||||||
const classNames = fn(d, i);
|
|
||||||
if (classNames !== className) {
|
|
||||||
return join(' ', [className, classNames]);
|
|
||||||
}
|
|
||||||
return classNames;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
}
|
|
28
packages/d3tooltip/src/utils/prependClass.ts
Normal file
28
packages/d3tooltip/src/utils/prependClass.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
7
packages/d3tooltip/tsconfig.json
Normal file
7
packages/d3tooltip/tsconfig.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.react.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "lib"
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
4
packages/d3tooltip/tsconfig.webpack.json
Normal file
4
packages/d3tooltip/tsconfig.webpack.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"include": ["webpack.config.umd.ts"]
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
const path = require('path');
|
import * as path from 'path';
|
||||||
|
|
||||||
module.exports = (env = {}) => ({
|
export default (env: { production?: boolean } = {}) => ({
|
||||||
mode: env.production ? 'production' : 'development',
|
mode: env.production ? 'production' : 'development',
|
||||||
entry: {
|
entry: {
|
||||||
app: ['./src/index.js'],
|
app: ['./src/index'],
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
library: 'd3tooltip',
|
library: 'd3tooltip',
|
||||||
|
@ -14,10 +14,13 @@ module.exports = (env = {}) => ({
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.(js|ts)$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||||
|
},
|
||||||
});
|
});
|
|
@ -47,7 +47,6 @@
|
||||||
"base16": "^1.0.0",
|
"base16": "^1.0.0",
|
||||||
"codemirror": "^5.56.0",
|
"codemirror": "^5.56.0",
|
||||||
"color": "^3.1.2",
|
"color": "^3.1.2",
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react-icons": "^3.10.0",
|
"react-icons": "^3.10.0",
|
||||||
"react-jsonschema-form": "^1.8.1",
|
"react-jsonschema-form": "^1.8.1",
|
||||||
|
|
|
@ -38,6 +38,11 @@ export class Select extends (PureComponent || Component)<SelectProps> {
|
||||||
neutral60: this.props.theme.base06,
|
neutral60: this.props.theme.base06,
|
||||||
neutral80: this.props.theme.base07,
|
neutral80: this.props.theme.base07,
|
||||||
},
|
},
|
||||||
|
spacing: {
|
||||||
|
...theme.spacing,
|
||||||
|
baseUnit: 2,
|
||||||
|
controlHeight: this.props.theme.inputHeight,
|
||||||
|
},
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React, { ComponentType } from 'react';
|
import React from 'react';
|
||||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
|
||||||
import getDefaultTheme, { Theme } from '../themes/default';
|
import getDefaultTheme, { Theme } from '../themes/default';
|
||||||
import { withTheme } from 'styled-components';
|
import { withTheme } from 'styled-components';
|
||||||
import { Base16Theme } from 'base16';
|
import { Base16Theme } from 'base16';
|
||||||
|
@ -9,33 +8,16 @@ export default <C extends React.ComponentType<any>>(
|
||||||
? C
|
? C
|
||||||
: never
|
: never
|
||||||
) => {
|
) => {
|
||||||
const ThemedComponent = React.forwardRef<C, React.ComponentProps<C>>(
|
return withTheme((props) => {
|
||||||
(props, ref) => {
|
return props.theme && props.theme.type ? (
|
||||||
// eslint-disable-next-line react/prop-types
|
<UnthemedComponent {...props} />
|
||||||
if (props.theme && props.theme.type) {
|
) : (
|
||||||
const ThemedComponent = withTheme(
|
<UnthemedComponent
|
||||||
UnthemedComponent as ComponentType<{ theme?: Theme }>
|
{...props}
|
||||||
);
|
theme={getDefaultTheme((props.theme ?? {}) as Base16Theme)}
|
||||||
return <ThemedComponent {...props} ref={ref} />;
|
/>
|
||||||
}
|
);
|
||||||
const UnthemedComponentAny = UnthemedComponent as any;
|
});
|
||||||
return (
|
|
||||||
<UnthemedComponentAny
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
theme={getDefaultTheme({} as Base16Theme)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
hoistNonReactStatics(ThemedComponent, UnthemedComponent);
|
|
||||||
|
|
||||||
ThemedComponent.displayName = `ThemedComponent(${
|
|
||||||
UnthemedComponent.displayName ?? 'Component'
|
|
||||||
})`;
|
|
||||||
|
|
||||||
return ThemedComponent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: memoize it?
|
// TODO: memoize it?
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"presets": ["@babel/preset-env"]
|
"presets": ["@babel/preset-env", "@babel/preset-typescript"],
|
||||||
|
"plugins": ["@babel/plugin-proposal-class-properties"]
|
||||||
}
|
}
|
||||||
|
|
3
packages/map2tree/.eslintignore
Normal file
3
packages/map2tree/.eslintignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
examples
|
||||||
|
lib
|
||||||
|
dist
|
29
packages/map2tree/.eslintrc.js
Normal file
29
packages/map2tree/.eslintrc.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['*.ts'],
|
||||||
|
extends: '../../eslintrc.ts.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['test/*.ts'],
|
||||||
|
extends: '../../eslintrc.ts.jest.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./test/tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['webpack.config.umd.ts'],
|
||||||
|
extends: '../../eslintrc.ts.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.webpack.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
3
packages/map2tree/jest.config.js
Normal file
3
packages/map2tree/jest.config.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
};
|
|
@ -2,20 +2,6 @@
|
||||||
"name": "map2tree",
|
"name": "map2tree",
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"description": "Utility for mapping maps to trees",
|
"description": "Utility for mapping maps to trees",
|
||||||
"main": "lib/index.js",
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rimraf lib dist",
|
|
||||||
"build": "babel src --out-dir lib",
|
|
||||||
"build:umd": "webpack --progress --config webpack.config.umd.js",
|
|
||||||
"build:umd:min": "webpack --env.production --progress --config webpack.config.umd.js",
|
|
||||||
"test": "jest",
|
|
||||||
"prepare": "npm run build && npm run build:umd",
|
|
||||||
"prepublishOnly": "npm run test && npm run clean && npm run build && npm run build:umd && npm run build:umd:min"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"map2tree",
|
"map2tree",
|
||||||
"map-to-tree",
|
"map-to-tree",
|
||||||
|
@ -23,38 +9,43 @@
|
||||||
"map",
|
"map",
|
||||||
"tree"
|
"tree"
|
||||||
],
|
],
|
||||||
"author": "romseguy",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/map2tree",
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"author": "romseguy",
|
||||||
"@babel/cli": "^7.10.5",
|
|
||||||
"@babel/core": "^7.11.1",
|
|
||||||
"@babel/preset-env": "^7.11.0",
|
|
||||||
"babel-loader": "^8.1.0",
|
|
||||||
"immutable": "^4.0.0-rc.12",
|
|
||||||
"jest": "^26.2.2",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"webpack": "^4.44.1",
|
|
||||||
"webpack-cli": "^3.3.12"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"lodash": "^4.17.19"
|
|
||||||
},
|
|
||||||
"npmName": "map2tree",
|
|
||||||
"files": [
|
"files": [
|
||||||
"lib",
|
"lib",
|
||||||
"dist",
|
"dist",
|
||||||
"src"
|
"src"
|
||||||
],
|
],
|
||||||
"npmFileMap": [
|
"main": "lib/index.js",
|
||||||
{
|
"types": "lib/index.d.ts",
|
||||||
"basePath": "/dist/",
|
"repository": {
|
||||||
"files": [
|
"type": "git",
|
||||||
"*.js"
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
]
|
},
|
||||||
}
|
"scripts": {
|
||||||
]
|
"build": "npm run build:types && npm run build:js && npm run build:umd && npm run build:umd:min",
|
||||||
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
|
"build:js": "babel src --out-dir lib --extensions \".ts\" --source-maps inline",
|
||||||
|
"build:umd": "webpack --progress --config webpack.config.umd.ts",
|
||||||
|
"build:umd:min": "webpack --env.production --progress --config webpack.config.umd.ts",
|
||||||
|
"clean": "rimraf lib dist",
|
||||||
|
"test": "jest",
|
||||||
|
"lint": "eslint . --ext .ts",
|
||||||
|
"lint:fix": "eslint . --ext .ts --fix",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"type-check:watch": "npm run type-check -- --watch",
|
||||||
|
"preversion": "npm run type-check && npm run lint && npm run test",
|
||||||
|
"prepublishOnly": "npm run clean && npm run build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lodash": "^4.17.19"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/lodash": "^4.14.159",
|
||||||
|
"immutable": "^4.0.0-rc.12"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
import isArray from 'lodash/isArray';
|
|
||||||
import isPlainObject from 'lodash/isPlainObject';
|
|
||||||
import mapValues from 'lodash/mapValues';
|
|
||||||
|
|
||||||
function visit(parent, visitFn, childrenFn) {
|
|
||||||
if (!parent) return;
|
|
||||||
|
|
||||||
visitFn(parent);
|
|
||||||
|
|
||||||
const children = childrenFn(parent);
|
|
||||||
if (children) {
|
|
||||||
const count = children.length;
|
|
||||||
for (let i = 0; i < count; i++) {
|
|
||||||
visit(children[i], visitFn, childrenFn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNode(tree, key) {
|
|
||||||
let node = null;
|
|
||||||
|
|
||||||
visit(
|
|
||||||
tree,
|
|
||||||
(d) => {
|
|
||||||
if (d.name === key) {
|
|
||||||
node = d;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(d) => d.children
|
|
||||||
);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function map2tree(
|
|
||||||
root,
|
|
||||||
options = {},
|
|
||||||
tree = { name: options.key || 'state', children: [] }
|
|
||||||
) {
|
|
||||||
if (!isPlainObject(root) && root && !root.toJS) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const { key: rootNodeKey = 'state', pushMethod = 'push' } = options;
|
|
||||||
const currentNode = getNode(tree, rootNodeKey);
|
|
||||||
|
|
||||||
if (currentNode === null) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
mapValues(root && root.toJS ? root.toJS() : root, (maybeImmutable, key) => {
|
|
||||||
const value =
|
|
||||||
maybeImmutable && maybeImmutable.toJS
|
|
||||||
? maybeImmutable.toJS()
|
|
||||||
: maybeImmutable;
|
|
||||||
let newNode = { name: key };
|
|
||||||
|
|
||||||
if (isArray(value)) {
|
|
||||||
newNode.children = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < value.length; i++) {
|
|
||||||
newNode.children[pushMethod]({
|
|
||||||
name: `${key}[${i}]`,
|
|
||||||
[isPlainObject(value[i]) ? 'object' : 'value']: value[i],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (isPlainObject(value)) {
|
|
||||||
newNode.children = [];
|
|
||||||
} else {
|
|
||||||
newNode.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentNode.children[pushMethod](newNode);
|
|
||||||
|
|
||||||
map2tree(value, { key, pushMethod }, tree);
|
|
||||||
});
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
100
packages/map2tree/src/index.ts
Normal file
100
packages/map2tree/src/index.ts
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
import isArray from 'lodash/isArray';
|
||||||
|
import isPlainObject from 'lodash/isPlainObject';
|
||||||
|
import mapValues from 'lodash/mapValues';
|
||||||
|
|
||||||
|
export interface Node {
|
||||||
|
name: string;
|
||||||
|
children?: Node[] | null;
|
||||||
|
value?: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
function visit(
|
||||||
|
parent: Node,
|
||||||
|
visitFn: (parent: Node) => void,
|
||||||
|
childrenFn: (parent: Node) => Node[] | undefined | null
|
||||||
|
) {
|
||||||
|
if (!parent) return;
|
||||||
|
|
||||||
|
visitFn(parent);
|
||||||
|
|
||||||
|
const children = childrenFn(parent);
|
||||||
|
if (children) {
|
||||||
|
const count = children.length;
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
visit(children[i], visitFn, childrenFn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNode(tree: Node, key: string): Node | null {
|
||||||
|
let node = null;
|
||||||
|
|
||||||
|
visit(
|
||||||
|
tree,
|
||||||
|
(d) => {
|
||||||
|
if (d.name === key) {
|
||||||
|
node = d;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(d) => d.children
|
||||||
|
);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function map2tree(
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
root: {},
|
||||||
|
options: { key?: string; pushMethod?: 'push' | 'unshift' } = {},
|
||||||
|
tree: Node = { name: options.key || 'state', children: [] }
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
): Node | {} {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
if (!isPlainObject(root) && root && !(root as { toJS: () => {} }).toJS) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { key: rootNodeKey = 'state', pushMethod = 'push' } = options;
|
||||||
|
const currentNode = getNode(tree, rootNodeKey);
|
||||||
|
|
||||||
|
if (currentNode === null) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
mapValues(
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
root && (root as { toJS: () => {} }).toJS
|
||||||
|
? // eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
(root as { toJS: () => {} }).toJS()
|
||||||
|
: root,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
(maybeImmutable: { toJS?: () => {} }, key) => {
|
||||||
|
const value =
|
||||||
|
maybeImmutable && maybeImmutable.toJS
|
||||||
|
? maybeImmutable.toJS()
|
||||||
|
: maybeImmutable;
|
||||||
|
const newNode: Node = { name: key };
|
||||||
|
|
||||||
|
if (isArray(value)) {
|
||||||
|
newNode.children = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < value.length; i++) {
|
||||||
|
newNode.children[pushMethod]({
|
||||||
|
name: `${key}[${i}]`,
|
||||||
|
[isPlainObject(value[i]) ? 'object' : 'value']: value[i],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (isPlainObject(value)) {
|
||||||
|
newNode.children = [];
|
||||||
|
} else {
|
||||||
|
newNode.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentNode.children;
|
||||||
|
|
||||||
|
map2tree(value, { key, pushMethod }, tree);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
8
packages/map2tree/test/map2tree.spec.js → packages/map2tree/test/map2tree.spec.ts
Executable file → Normal file
8
packages/map2tree/test/map2tree.spec.js → packages/map2tree/test/map2tree.spec.ts
Executable file → Normal file
|
@ -1,11 +1,11 @@
|
||||||
import map2tree from '../src';
|
import map2tree, { Node } from '../src';
|
||||||
import immutable from 'immutable';
|
import * as immutable from 'immutable';
|
||||||
|
|
||||||
test('# rootNodeKey', () => {
|
test('# rootNodeKey', () => {
|
||||||
const map = {};
|
const map = {};
|
||||||
const options = { key: 'foo' };
|
const options = { key: 'foo' };
|
||||||
|
|
||||||
expect(map2tree(map, options).name).toBe('foo');
|
expect((map2tree(map, options) as Node).name).toBe('foo');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('# shallow map', () => {
|
describe('# shallow map', () => {
|
||||||
|
@ -151,7 +151,7 @@ describe('# array map', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('## unshift', () => {
|
test('## unshift', () => {
|
||||||
const options = { pushMethod: 'unshift' };
|
const options = { pushMethod: 'unshift' as const };
|
||||||
const expected = {
|
const expected = {
|
||||||
name: 'state',
|
name: 'state',
|
||||||
children: [
|
children: [
|
4
packages/map2tree/test/tsconfig.json
Normal file
4
packages/map2tree/test/tsconfig.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.base.json",
|
||||||
|
"include": ["../src", "."]
|
||||||
|
}
|
7
packages/map2tree/tsconfig.json
Normal file
7
packages/map2tree/tsconfig.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.react.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "lib"
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
4
packages/map2tree/tsconfig.webpack.json
Normal file
4
packages/map2tree/tsconfig.webpack.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"include": ["webpack.config.umd.ts"]
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
const path = require('path');
|
import * as path from 'path';
|
||||||
|
|
||||||
module.exports = (env = {}) => ({
|
export default (env: { production?: boolean } = {}) => ({
|
||||||
mode: env.production ? 'production' : 'development',
|
mode: env.production ? 'production' : 'development',
|
||||||
entry: {
|
entry: {
|
||||||
app: ['./src/index.js'],
|
app: ['./src/index'],
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
library: 'd3tooltip',
|
library: 'map2tree',
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
filename: env.production ? 'map2tree.min.js' : 'map2tree.js',
|
filename: env.production ? 'map2tree.min.js' : 'map2tree.js',
|
||||||
|
@ -14,10 +14,13 @@ module.exports = (env = {}) => ({
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.(js|ts)$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||||
|
},
|
||||||
});
|
});
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"presets": ["@babel/preset-env", "@babel/preset-react"],
|
"presets": [
|
||||||
"plugins": [
|
"@babel/preset-env",
|
||||||
"@babel/plugin-proposal-class-properties",
|
"@babel/preset-react",
|
||||||
"@babel/plugin-proposal-export-default-from"
|
"@babel/preset-typescript"
|
||||||
]
|
],
|
||||||
|
"plugins": ["@babel/plugin-proposal-class-properties"]
|
||||||
}
|
}
|
||||||
|
|
1
packages/redux-devtools-chart-monitor/.eslintignore
Normal file
1
packages/redux-devtools-chart-monitor/.eslintignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
lib
|
13
packages/redux-devtools-chart-monitor/.eslintrc.js
Normal file
13
packages/redux-devtools-chart-monitor/.eslintrc.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['*.ts', '*.tsx'],
|
||||||
|
extends: '../../eslintrc.ts.react.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -2,21 +2,6 @@
|
||||||
"name": "redux-devtools-chart-monitor",
|
"name": "redux-devtools-chart-monitor",
|
||||||
"version": "1.7.2",
|
"version": "1.7.2",
|
||||||
"description": "Chart monitor for Redux DevTools",
|
"description": "Chart monitor for Redux DevTools",
|
||||||
"main": "lib/index.js",
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rimraf lib",
|
|
||||||
"build": "babel src --out-dir lib",
|
|
||||||
"prepare": "npm run build",
|
|
||||||
"prepublishOnly": "npm run clean && npm run build"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"lib",
|
|
||||||
"src"
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"redux",
|
"redux",
|
||||||
"devtools",
|
"devtools",
|
||||||
|
@ -24,32 +9,52 @@
|
||||||
"react",
|
"react",
|
||||||
"chart"
|
"chart"
|
||||||
],
|
],
|
||||||
"author": "romseguy",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-chart-monitor",
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"author": "romseguy",
|
||||||
"@babel/cli": "^7.10.5",
|
"files": [
|
||||||
"@babel/core": "^7.11.1",
|
"lib",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
"src"
|
||||||
"@babel/plugin-proposal-export-default-from": "^7.10.4",
|
],
|
||||||
"@babel/preset-env": "^7.11.0",
|
"main": "lib/index.js",
|
||||||
"@babel/preset-react": "^7.10.4",
|
"types": "lib/index.d.ts",
|
||||||
"babel-loader": "^8.1.0",
|
"repository": {
|
||||||
"rimraf": "^3.0.2"
|
"type": "git",
|
||||||
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"scripts": {
|
||||||
"react": "^16.3.0",
|
"build": "npm run build:types && npm run build:js",
|
||||||
"react-dom": "^16.3.0",
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
"redux-devtools": "^3.0.0"
|
"build:js": "babel src --out-dir lib --extensions \".ts,.tsx\" --source-maps inline",
|
||||||
|
"clean": "rimraf lib",
|
||||||
|
"lint": "eslint . --ext .ts,.tsx",
|
||||||
|
"lint:fix": "eslint . --ext .ts,.tsx --fix",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"type-check:watch": "npm run type-check -- --watch",
|
||||||
|
"preversion": "npm run type-check && npm run lint",
|
||||||
|
"prepublishOnly": "npm run clean && npm run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/prop-types": "^15.7.3",
|
||||||
|
"@types/redux-devtools-themes": "^1.0.0",
|
||||||
"d3-state-visualizer": "^1.3.4",
|
"d3-state-visualizer": "^1.3.4",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react-pure-render": "^1.0.2",
|
|
||||||
"redux-devtools-themes": "^1.0.0"
|
"redux-devtools-themes": "^1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^16.9.46",
|
||||||
|
"react": "^16.13.1",
|
||||||
|
"redux": "^4.0.5",
|
||||||
|
"redux-devtools": "^3.7.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "^16.3.18",
|
||||||
|
"react": "^16.3.0",
|
||||||
|
"redux": "^3.4.0 || ^4.0.0",
|
||||||
|
"redux-devtools": "^3.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,44 @@
|
||||||
import React, { Component, createRef } from 'react';
|
import React, { Component, createRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { tree } from 'd3-state-visualizer';
|
import { tree } from 'd3-state-visualizer';
|
||||||
|
import { Action, Dispatch } from 'redux';
|
||||||
|
import { LiftedAction, LiftedState } from 'redux-devtools-instrument';
|
||||||
|
import * as themes from 'redux-devtools-themes';
|
||||||
|
import { Base16Theme } from 'react-base16-styling';
|
||||||
|
import { ChartMonitorState } from './reducers';
|
||||||
|
import { Primitive } from 'd3';
|
||||||
|
|
||||||
const wrapperStyle = {
|
const wrapperStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
};
|
};
|
||||||
|
|
||||||
class Chart extends Component {
|
export interface Props<S, A extends Action<unknown>>
|
||||||
|
extends LiftedState<S, A, ChartMonitorState> {
|
||||||
|
dispatch: Dispatch<LiftedAction<S, A, ChartMonitorState>>;
|
||||||
|
preserveScrollTop: boolean;
|
||||||
|
select: (state: S) => unknown;
|
||||||
|
theme: keyof typeof themes | Base16Theme;
|
||||||
|
invertTheme: boolean;
|
||||||
|
|
||||||
|
state: S | null;
|
||||||
|
isSorted: boolean;
|
||||||
|
heightBetweenNodesCoeff: number;
|
||||||
|
widthBetweenNodesCoeff: number;
|
||||||
|
tooltipOptions: {
|
||||||
|
disabled: boolean;
|
||||||
|
offset: {
|
||||||
|
left: number;
|
||||||
|
top: number;
|
||||||
|
};
|
||||||
|
indentationSize: number;
|
||||||
|
style: { [key: string]: Primitive } | undefined;
|
||||||
|
};
|
||||||
|
style: { [key: string]: Primitive } | undefined;
|
||||||
|
defaultIsVisible?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Chart<S, A extends Action<unknown>> extends Component<Props<S, A>> {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
state: PropTypes.object,
|
state: PropTypes.object,
|
||||||
rootKeyName: PropTypes.string,
|
rootKeyName: PropTypes.string,
|
||||||
|
@ -60,21 +91,25 @@ class Chart extends Component {
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
divRef = createRef();
|
divRef = createRef<HTMLDivElement>();
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
renderChart?: (state?: {} | null | undefined) => void;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { select, state, defaultIsVisible } = this.props;
|
const { select, state, defaultIsVisible } = this.props;
|
||||||
this.renderChart = tree(this.divRef.current, this.props);
|
this.renderChart = tree(this.divRef.current!, this.props);
|
||||||
if (defaultIsVisible) {
|
if (defaultIsVisible) {
|
||||||
this.renderChart(select(state));
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
this.renderChart(select(state!) as {} | null | undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
UNSAFE_componentWillReceiveProps(nextProps: Props<S, A>) {
|
||||||
const { state, select, monitorState } = nextProps;
|
const { state, select, monitorState } = nextProps;
|
||||||
|
|
||||||
if (monitorState.isVisible !== false) {
|
if (monitorState.isVisible !== false) {
|
||||||
this.renderChart(select(state));
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
this.renderChart!(select(state!) as {} | null | undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import React, { Component } from 'react';
|
import React, { CSSProperties, PureComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import shouldPureComponentUpdate from 'react-pure-render/function';
|
|
||||||
import * as themes from 'redux-devtools-themes';
|
import * as themes from 'redux-devtools-themes';
|
||||||
import { ActionCreators } from 'redux-devtools';
|
import { ActionCreators, LiftedAction, LiftedState } from 'redux-devtools';
|
||||||
import deepmerge from 'deepmerge';
|
import deepmerge from 'deepmerge';
|
||||||
|
import { Action, Dispatch } from 'redux';
|
||||||
|
import { Base16Theme } from 'react-base16-styling';
|
||||||
|
|
||||||
import reducer from './reducers';
|
import reducer, { ChartMonitorState } from './reducers';
|
||||||
import Chart from './Chart';
|
import Chart, { Props } from './Chart';
|
||||||
|
import { Primitive } from 'd3';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const { reset, rollback, commit, sweep, toggleAction } = ActionCreators;
|
const { reset, rollback, commit, sweep, toggleAction } = ActionCreators;
|
||||||
|
|
||||||
const styles = {
|
const styles: { container: CSSProperties } = {
|
||||||
container: {
|
container: {
|
||||||
fontFamily: 'monaco, Consolas, Lucida Console, monospace',
|
fontFamily: 'monaco, Consolas, Lucida Console, monospace',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
@ -20,7 +23,7 @@ const styles = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function invertColors(theme) {
|
function invertColors(theme: Base16Theme) {
|
||||||
return {
|
return {
|
||||||
...theme,
|
...theme,
|
||||||
base00: theme.base07,
|
base00: theme.base07,
|
||||||
|
@ -34,7 +37,43 @@ function invertColors(theme) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChartMonitor extends Component {
|
export interface ChartMonitorProps<S, A extends Action<unknown>>
|
||||||
|
extends LiftedState<S, A, ChartMonitorState> {
|
||||||
|
dispatch: Dispatch<LiftedAction<S, A, ChartMonitorState>>;
|
||||||
|
preserveScrollTop: boolean;
|
||||||
|
select: (state: S) => unknown;
|
||||||
|
theme: keyof typeof themes | Base16Theme;
|
||||||
|
invertTheme: boolean;
|
||||||
|
|
||||||
|
state: S | null;
|
||||||
|
isSorted: boolean;
|
||||||
|
heightBetweenNodesCoeff: number;
|
||||||
|
widthBetweenNodesCoeff: number;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChartMonitor<S, A extends Action<unknown>> extends PureComponent<
|
||||||
|
ChartMonitorProps<S, A>
|
||||||
|
> {
|
||||||
static update = reducer;
|
static update = reducer;
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -55,45 +94,34 @@ class ChartMonitor extends Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
select: (state) => state,
|
select: (state: unknown) => state,
|
||||||
theme: 'nicinabox',
|
theme: 'nicinabox',
|
||||||
preserveScrollTop: true,
|
preserveScrollTop: true,
|
||||||
invertTheme: false,
|
invertTheme: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
shouldComponentUpdate = shouldPureComponentUpdate;
|
handleRollback = () => {
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.handleToggleAction = this.handleToggleAction.bind(this);
|
|
||||||
this.handleReset = this.handleReset.bind(this);
|
|
||||||
this.handleRollback = this.handleRollback.bind(this);
|
|
||||||
this.handleSweep = this.handleSweep.bind(this);
|
|
||||||
this.handleCommit = this.handleCommit.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleRollback() {
|
|
||||||
this.props.dispatch(rollback());
|
this.props.dispatch(rollback());
|
||||||
}
|
};
|
||||||
|
|
||||||
handleSweep() {
|
handleSweep = () => {
|
||||||
this.props.dispatch(sweep());
|
this.props.dispatch(sweep());
|
||||||
}
|
};
|
||||||
|
|
||||||
handleCommit() {
|
handleCommit = () => {
|
||||||
this.props.dispatch(commit());
|
this.props.dispatch(commit());
|
||||||
}
|
};
|
||||||
|
|
||||||
handleToggleAction(id) {
|
handleToggleAction = (id: number) => {
|
||||||
this.props.dispatch(toggleAction(id));
|
this.props.dispatch(toggleAction(id));
|
||||||
}
|
};
|
||||||
|
|
||||||
handleReset() {
|
handleReset = () => {
|
||||||
this.props.dispatch(reset());
|
this.props.dispatch(reset());
|
||||||
}
|
};
|
||||||
|
|
||||||
getTheme() {
|
getTheme() {
|
||||||
let { theme, invertTheme } = this.props;
|
const { theme, invertTheme } = this.props;
|
||||||
if (typeof theme !== 'string') {
|
if (typeof theme !== 'string') {
|
||||||
return invertTheme ? invertColors(theme) : theme;
|
return invertTheme ? invertColors(theme) : theme;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +130,6 @@ class ChartMonitor extends Component {
|
||||||
return invertTheme ? invertColors(themes[theme]) : themes[theme];
|
return invertTheme ? invertColors(themes[theme]) : themes[theme];
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.warn(
|
console.warn(
|
||||||
'DevTools theme ' + theme + ' not found, defaulting to nicinabox'
|
'DevTools theme ' + theme + ' not found, defaulting to nicinabox'
|
||||||
);
|
);
|
||||||
|
@ -132,7 +159,7 @@ class ChartMonitor extends Component {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getChartOptions(props = this.props) {
|
getChartOptions(props = this.props): Props<S, A> {
|
||||||
const { computedStates } = props;
|
const { computedStates } = props;
|
||||||
const theme = this.getTheme();
|
const theme = this.getTheme();
|
||||||
|
|
||||||
|
@ -156,7 +183,9 @@ class ChartMonitor extends Component {
|
||||||
heightBetweenNodesCoeff: 1,
|
heightBetweenNodesCoeff: 1,
|
||||||
widthBetweenNodesCoeff: 1.3,
|
widthBetweenNodesCoeff: 1.3,
|
||||||
tooltipOptions,
|
tooltipOptions,
|
||||||
style: this.getChartStyle(),
|
style: (this.getChartStyle() as unknown) as
|
||||||
|
| { [key: string]: Primitive }
|
||||||
|
| undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
return deepmerge(defaultOptions, props);
|
return deepmerge(defaultOptions, props);
|
||||||
|
@ -165,9 +194,10 @@ class ChartMonitor extends Component {
|
||||||
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 }}>
|
||||||
<Chart {...this.getChartOptions()} />
|
<ChartAsAny {...this.getChartOptions()} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -1,2 +0,0 @@
|
||||||
export const TOGGLE_VISIBILITY =
|
|
||||||
'@@redux-devtools-log-monitor/TOGGLE_VISIBILITY';
|
|
6
packages/redux-devtools-chart-monitor/src/actions.ts
Normal file
6
packages/redux-devtools-chart-monitor/src/actions.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export const TOGGLE_VISIBILITY =
|
||||||
|
'@@redux-devtools-log-monitor/TOGGLE_VISIBILITY';
|
||||||
|
interface ToggleVisibilityAction {
|
||||||
|
type: typeof TOGGLE_VISIBILITY;
|
||||||
|
}
|
||||||
|
export type ChartMonitorAction = ToggleVisibilityAction;
|
|
@ -1 +0,0 @@
|
||||||
export default from './ChartMonitor';
|
|
1
packages/redux-devtools-chart-monitor/src/index.ts
Normal file
1
packages/redux-devtools-chart-monitor/src/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { default } from './ChartMonitor';
|
|
@ -1,19 +0,0 @@
|
||||||
import { TOGGLE_VISIBILITY } from './actions';
|
|
||||||
|
|
||||||
function toggleVisibility(props, state = props.defaultIsVisible, action) {
|
|
||||||
if (action.type === TOGGLE_VISIBILITY) {
|
|
||||||
return !state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.defaultIsVisible !== undefined) {
|
|
||||||
return props.defaultIsVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function reducer(props, state = {}, action) {
|
|
||||||
return {
|
|
||||||
isVisible: toggleVisibility(props, state.isVisible, action),
|
|
||||||
};
|
|
||||||
}
|
|
33
packages/redux-devtools-chart-monitor/src/reducers.ts
Normal file
33
packages/redux-devtools-chart-monitor/src/reducers.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { Action } from 'redux';
|
||||||
|
import { ChartMonitorAction, TOGGLE_VISIBILITY } from './actions';
|
||||||
|
import { ChartMonitorProps } from './ChartMonitor';
|
||||||
|
|
||||||
|
function toggleVisibility<S, A extends Action<unknown>>(
|
||||||
|
props: ChartMonitorProps<S, A>,
|
||||||
|
state = props.defaultIsVisible,
|
||||||
|
action: ChartMonitorAction
|
||||||
|
): boolean {
|
||||||
|
if (action.type === TOGGLE_VISIBILITY) {
|
||||||
|
return !state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.defaultIsVisible !== undefined) {
|
||||||
|
return props.defaultIsVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChartMonitorState {
|
||||||
|
isVisible?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function reducer<S, A extends Action<unknown>>(
|
||||||
|
props: ChartMonitorProps<S, A>,
|
||||||
|
state: ChartMonitorState | undefined = {},
|
||||||
|
action: ChartMonitorAction
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
isVisible: toggleVisibility(props, state.isVisible, action),
|
||||||
|
};
|
||||||
|
}
|
7
packages/redux-devtools-chart-monitor/tsconfig.json
Normal file
7
packages/redux-devtools-chart-monitor/tsconfig.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.react.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "lib"
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import { Action, Dispatch } from 'redux';
|
||||||
import * as themes from 'redux-devtools-themes';
|
import * as themes from 'redux-devtools-themes';
|
||||||
import { Base16Theme } from 'redux-devtools-themes';
|
import { Base16Theme } from 'redux-devtools-themes';
|
||||||
import { ActionCreators, LiftedAction, LiftedState } from 'redux-devtools';
|
import { ActionCreators, LiftedAction, LiftedState } from 'redux-devtools';
|
||||||
|
import debounce from 'lodash.debounce';
|
||||||
import {
|
import {
|
||||||
updateScrollTop,
|
updateScrollTop,
|
||||||
startConsecutiveToggle,
|
startConsecutiveToggle,
|
||||||
|
@ -12,9 +13,6 @@ import {
|
||||||
import reducer, { LogMonitorState } from './reducers';
|
import reducer, { LogMonitorState } from './reducers';
|
||||||
import LogMonitorButtonBar from './LogMonitorButtonBar';
|
import LogMonitorButtonBar from './LogMonitorButtonBar';
|
||||||
import LogMonitorEntryList from './LogMonitorEntryList';
|
import LogMonitorEntryList from './LogMonitorEntryList';
|
||||||
import debounce from 'lodash.debounce';
|
|
||||||
import { DockMonitorState } from 'redux-devtools-dock-monitor/lib/reducers';
|
|
||||||
import { DockMonitorAction } from 'redux-devtools-dock-monitor/lib/actions';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const { toggleAction, setActionsActive } = ActionCreators;
|
const { toggleAction, setActionsActive } = ActionCreators;
|
||||||
|
@ -276,8 +274,8 @@ export default (LogMonitor as unknown) as React.ComponentType<
|
||||||
> & {
|
> & {
|
||||||
update(
|
update(
|
||||||
monitorProps: ExternalProps<unknown, Action<unknown>>,
|
monitorProps: ExternalProps<unknown, Action<unknown>>,
|
||||||
state: DockMonitorState | undefined,
|
state: LogMonitorState | undefined,
|
||||||
action: DockMonitorAction
|
action: LogMonitorAction
|
||||||
): DockMonitorState;
|
): LogMonitorState;
|
||||||
defaultProps: DefaultProps<unknown>;
|
defaultProps: DefaultProps<unknown>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React, { PureComponent, Component, ReactNode } from 'react';
|
import React, { PureComponent, Component, ReactNode } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { stringify } from 'javascript-stringify';
|
import { stringify } from 'javascript-stringify';
|
||||||
import objectPath from 'object-path';
|
import objectPath from 'object-path';
|
||||||
import jsan from 'jsan';
|
import jsan from 'jsan';
|
||||||
|
|
|
@ -130,14 +130,15 @@ export default class TestTab<S, A extends Action<unknown>> extends Component<
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Select
|
<div style={{ flexGrow: 1, zIndex: 100 }}>
|
||||||
options={templates}
|
<Select
|
||||||
valueKey="name"
|
options={templates}
|
||||||
labelKey="name"
|
getOptionValue={(template: Template) => template.name}
|
||||||
value={name}
|
getOptionLabel={(template: Template) => template.name}
|
||||||
simpleValue={false}
|
value={templates.filter((template) => template.name === name)}
|
||||||
onChange={this.handleSelectTemplate}
|
onChange={this.handleSelectTemplate}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<Button onClick={this.editTemplate}>
|
<Button onClick={this.editTemplate}>
|
||||||
<MdEdit />
|
<MdEdit />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
19
yarn.lock
19
yarn.lock
|
@ -3355,6 +3355,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/d3@^3.5.43":
|
||||||
|
version "3.5.43"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.43.tgz#e9b4992817e0b6c5efaa7d6e5bb2cee4d73eab58"
|
||||||
|
integrity sha512-t9ZmXOcpVxywRw86YtIC54g7M9puRh8hFedRvVfHKf5YyOP6pSxA0TvpXpfseXSCInoW4P7bggTrSDiUOs4g5w==
|
||||||
|
|
||||||
"@types/dateformat@^3.0.1":
|
"@types/dateformat@^3.0.1":
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/dateformat/-/dateformat-3.0.1.tgz#98d747a2e5e9a56070c6bf14e27bff56204e34cc"
|
resolved "https://registry.yarnpkg.com/@types/dateformat/-/dateformat-3.0.1.tgz#98d747a2e5e9a56070c6bf14e27bff56204e34cc"
|
||||||
|
@ -3675,6 +3680,13 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a"
|
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a"
|
||||||
integrity sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==
|
integrity sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==
|
||||||
|
|
||||||
|
"@types/ramda@^0.27.17":
|
||||||
|
version "0.27.17"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.27.17.tgz#b4359d29614994dbb4c70e504b268bd9f0388bb0"
|
||||||
|
integrity sha512-AHVwr1YdFdxeabfC1g34ZuJ61dKOcfdXlG+sqGUweD+5VrD6A9emwmc2OZY+N8CdEKdwl29hwvtTMSJ6ZVVsiQ==
|
||||||
|
dependencies:
|
||||||
|
ts-toolbelt "^6.3.3"
|
||||||
|
|
||||||
"@types/range-parser@*":
|
"@types/range-parser@*":
|
||||||
version "1.2.3"
|
version "1.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
||||||
|
@ -9357,7 +9369,7 @@ hmac-drbg@^1.0.0:
|
||||||
minimalistic-assert "^1.0.0"
|
minimalistic-assert "^1.0.0"
|
||||||
minimalistic-crypto-utils "^1.0.1"
|
minimalistic-crypto-utils "^1.0.1"
|
||||||
|
|
||||||
hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
|
hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0:
|
||||||
version "3.3.2"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||||
|
@ -16929,6 +16941,11 @@ ts-pnp@^1.1.6:
|
||||||
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
|
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
|
||||||
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
|
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
|
||||||
|
|
||||||
|
ts-toolbelt@^6.3.3:
|
||||||
|
version "6.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz#cb3b43ed725cb63644782c64fbcad7d8f28c0a83"
|
||||||
|
integrity sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==
|
||||||
|
|
||||||
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||||
version "1.13.0"
|
version "1.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user