Browse Source

use new core with models

pull/1/head
vargburz 3 years ago
parent
commit
fd3e15d30f
  1. 7
      package.json
  2. 139
      src/index.ts
  3. 46
      src/models/bar_options.ts
  4. 15
      src/models/bar_series.ts
  5. 33
      src/types.ts
  6. 10
      yarn.lock

7
package.json

@ -1,12 +1,13 @@
{ {
"name": "@chartwerk/bar-pod", "name": "@chartwerk/bar-pod",
"version": "0.6.0-beta", "version": "0.6.1",
"description": "Chartwerk bar pod", "description": "Chartwerk bar pod",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
"build": "webpack --config build/webpack.prod.conf.js && webpack --config build/webpack.dev.conf.js", "build": "webpack --config build/webpack.prod.conf.js && webpack --config build/webpack.dev.conf.js",
"dev": "webpack --watch --config build/webpack.dev.conf.js", "dev": "webpack --watch --config build/webpack.dev.conf.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1",
"update-core": "yarn up @chartwerk/core && yarn up @chartwerk/core@latest"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -15,7 +16,7 @@
"author": "CorpGlory", "author": "CorpGlory",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@chartwerk/core": "0.6.3" "@chartwerk/core": "latest"
}, },
"devDependencies": { "devDependencies": {
"css-loader": "^3.4.2", "css-loader": "^3.4.2",

139
src/index.ts

@ -1,29 +1,29 @@
import { ChartwerkPod, VueChartwerkPodMixin, TickOrientation, TimeFormat, AxisFormat } from '@chartwerk/core'; import { ChartwerkPod, VueChartwerkPodMixin, TimeFormat, AxisFormat } from '@chartwerk/core';
import { BarTimeSerie, BarOptions, RowValues } from './types'; import { BarConfig } from './models/bar_options';
import { BarSeries } from './models/bar_series';
import { BarSerie, BarOptions, RowValues } from './types';
import { findClosest } from './utils'; import { findClosest } from './utils';
import * as d3 from 'd3'; import * as d3 from 'd3';
import * as _ from 'lodash'; import * as _ from 'lodash';
const DEFAULT_BAR_OPTIONS: BarOptions = { export class ChartwerkBarPod extends ChartwerkPod<BarSerie, BarOptions> {
renderBarLabels: false,
stacked: false,
matching: false
}
export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
barYScale: null | d3.ScaleLinear<number, number> = null; barYScale: null | d3.ScaleLinear<number, number> = null;
_seriesDataForRendring = []; _seriesDataForRendring = [];
series: BarSeries;
options: BarConfig;
constructor(el: HTMLElement, _series: BarTimeSerie[] = [], _options: BarOptions = {}) { constructor(el: HTMLElement, _series: BarSerie[] = [], _options: BarOptions = {}) {
super(el, _series, _options); super(el, _series, _options);
_.defaults(this.options, DEFAULT_BAR_OPTIONS); this.series = new BarSeries(_series);
this.options = new BarConfig(_options);
} }
protected renderMetrics(): void { protected renderMetrics(): void {
if(this.series.length === 0 || this.series[0].datapoints.length === 0) { if(!this.series.isSeriesAvailable) {
this.renderNoDataPointsMessage(); this.renderNoDataPointsMessage();
return; return;
} }
@ -34,15 +34,15 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
} }
get isMatchingDisabled(): boolean { get isMatchingDisabled(): boolean {
return this.options.matching === false || this.seriesUniqKeys.length === 0; return this.options.barOptions.matching === false || this.seriesUniqKeys.length === 0;
} }
setSeriesDataForRendering(): void { setSeriesDataForRendering(): void {
if(this.isMatchingDisabled) { if(this.isMatchingDisabled) {
this._seriesDataForRendring = this.getZippedDataForRender(this.visibleSeries); this._seriesDataForRendring = this.getZippedDataForRender(this.series.visibleSeries);
} else { } else {
const matchedSeries = this.seriesForMatching.map( const matchedSeries = this.seriesForMatching.map(
(series: BarTimeSerie[], idx: number) => this.getZippedDataForRender(series) (series: BarSerie[], idx: number) => this.getZippedDataForRender(series)
); );
this._seriesDataForRendring = this.mergeMacthedSeriesAndSort(matchedSeries); this._seriesDataForRendring = this.mergeMacthedSeriesAndSort(matchedSeries);
} }
@ -77,7 +77,7 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
.on('contextmenu', this.contextMenu.bind(this)); .on('contextmenu', this.contextMenu.bind(this));
// render bar annotations, its all hardcoded // render bar annotations, its all hardcoded
if(_.isEmpty(this.options.annotations)) { if(_.isEmpty(this.options.barOptions.annotations)) {
return; return;
} }
// find all series for single matchedKey // find all series for single matchedKey
@ -86,7 +86,7 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
const key = matchedKeys[0]; const key = matchedKeys[0];
const lastRect = _.last(container.selectAll('rect')?.nodes()); const lastRect = _.last(container.selectAll('rect')?.nodes());
const annotation = _.find(this.options.annotations, a => a.key === key); const annotation = _.find(this.options.barOptions.annotations, a => a.key === key);
if(!lastRect || !key || !annotation) { if(!lastRect || !key || !annotation) {
return; return;
} }
@ -97,7 +97,7 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
.attr('d', () => { .attr('d', () => {
const x = Math.ceil(_.toNumber(rectSelection.attr('x'))); const x = Math.ceil(_.toNumber(rectSelection.attr('x')));
const y = Math.ceil(_.toNumber(rectSelection.attr('y'))); const y = Math.ceil(_.toNumber(rectSelection.attr('y')));
const options = { max: this.options.maxAnnotationSize, min: this.options.minAnnotationSize }; const options = { max: this.options.barOptions.maxAnnotationSize, min: this.options.barOptions.minAnnotationSize };
return this.getTrianglePath(x, y, this.barWidth, options); return this.getTrianglePath(x, y, this.barWidth, options);
}) })
.attr('fill', annotation.color); .attr('fill', annotation.color);
@ -132,10 +132,10 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
} }
getBarOpacity(rowValues: RowValues): number { getBarOpacity(rowValues: RowValues): number {
if(this.options.opacityFormatter === undefined) { if(this.options.barOptions.opacityFormatter === undefined) {
return 1; return 1;
} }
return this.options.opacityFormatter(rowValues); return this.options.barOptions.opacityFormatter(rowValues);
} }
mergeMacthedSeriesAndSort(matchedSeries: any[]) { mergeMacthedSeriesAndSort(matchedSeries: any[]) {
@ -155,27 +155,27 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
} }
get seriesUniqKeys(): string[] { get seriesUniqKeys(): string[] {
if(this.visibleSeries.length === 0) { if(!this.series.isSeriesAvailable) {
return []; return [];
} }
const keys = this.visibleSeries.map(serie => serie.matchedKey); const keys = this.series.visibleSeries.map(serie => serie.matchedKey);
const uniqKeys = _.uniq(keys); const uniqKeys = _.uniq(keys);
const filteredKeys = _.filter(uniqKeys, key => key !== undefined); const filteredKeys = _.filter(uniqKeys, key => key !== undefined);
return filteredKeys; return filteredKeys;
} }
get seriesForMatching(): BarTimeSerie[][] { get seriesForMatching(): BarSerie[][] {
if(this.seriesUniqKeys.length === 0) { if(this.seriesUniqKeys.length === 0) {
return [this.visibleSeries]; return [this.series.visibleSeries];
} }
const seriesList = this.seriesUniqKeys.map(key => { const seriesList = this.seriesUniqKeys.map(key => {
const seriesWithKey = _.filter(this.visibleSeries, serie => serie.matchedKey === key); const seriesWithKey = _.filter(this.series.visibleSeries, serie => serie.matchedKey === key);
return seriesWithKey; return seriesWithKey;
}); });
return seriesList; return seriesList;
} }
getZippedDataForRender(series: BarTimeSerie[]): RowValues[] { getZippedDataForRender(series: BarSerie[]): RowValues[] {
if(series.length === 0) { if(series.length === 0) {
throw new Error('There is no visible series'); throw new Error('There is no visible series');
} }
@ -185,7 +185,7 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
const additionalValuesColumns = _.map(series, serie => _.map(serie.datapoints, row => row[2] !== undefined ? row[2] : null)); const additionalValuesColumns = _.map(series, serie => _.map(serie.datapoints, row => row[2] !== undefined ? row[2] : null));
const zippedAdditionalValuesColumn = _.zip(...additionalValuesColumns); const zippedAdditionalValuesColumn = _.zip(...additionalValuesColumns);
const zippedValuesColumn = _.zip(...valuesColumns); const zippedValuesColumn = _.zip(...valuesColumns);
const colors = _.map(series, serie => this.getBarColor(serie)); const colors = _.map(series, serie => serie.color);
const tagrets = _.map(series, serie => serie.target); const tagrets = _.map(series, serie => serie.target);
const zippedData = _.zip(keysColumn, zippedValuesColumn, zippedAdditionalValuesColumn, tagrets); const zippedData = _.zip(keysColumn, zippedValuesColumn, zippedAdditionalValuesColumn, tagrets);
const data = _.map(zippedData, row => { return { key: row[0], values: row[1], additionalValues: row[2], colors, serieTarget: tagrets } }); const data = _.map(zippedData, row => { return { key: row[0], values: row[1], additionalValues: row[2], colors, serieTarget: tagrets } });
@ -195,7 +195,7 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
public renderSharedCrosshair(values: { x?: number, y?: number }): void { public renderSharedCrosshair(values: { x?: number, y?: number }): void {
this.crosshair.style('display', null); this.crosshair.style('display', null);
const x = this.xScale(values.x); const x = this.state.xScale(values.x);
this.crosshair.select('#crosshair-line-x') this.crosshair.select('#crosshair-line-x')
.attr('x1', x) .attr('x1', x)
.attr('x2', x); .attr('x2', x);
@ -209,59 +209,40 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
// TODO: mouse move work bad with matching // TODO: mouse move work bad with matching
const event = d3.mouse(this.chartContainer.node()); const event = d3.mouse(this.chartContainer.node());
const eventX = event[0]; const eventX = event[0];
if(this.isOutOfChart() === true) {
this.crosshair.style('display', 'none');
return;
}
this.crosshair.select('#crosshair-line-x') this.crosshair.select('#crosshair-line-x')
.attr('x1', eventX) .attr('x1', eventX)
.attr('x2', eventX); .attr('x2', eventX);
const series = this.getSeriesPointFromMousePosition(eventX); const series = this.getSeriesPointFromMousePosition(eventX);
if(this.options.eventsCallbacks !== undefined && this.options.eventsCallbacks.mouseMove !== undefined) { this.options.callbackMouseMove({
this.options.eventsCallbacks.mouseMove({
x: d3.event.pageX, x: d3.event.pageX,
y: d3.event.pageY, y: d3.event.pageY,
time: this.xScale.invert(eventX), time: this.state.xScale.invert(eventX),
series, series,
chartX: eventX, chartX: eventX,
chartWidth: this.width chartWidth: this.width
}); });
} else {
console.log('mouse move, but there is no callback');
}
} }
getSeriesPointFromMousePosition(eventX: number): any[] | undefined { getSeriesPointFromMousePosition(eventX: number): any[] | undefined {
if(this.series === undefined || this.series.length === 0) { if(!this.series.isSeriesAvailable) {
return undefined; return undefined;
} }
const mousePoisitionKey = Math.ceil(this.xScale.invert(eventX)); const mousePoisitionKey = Math.ceil(this.state.xScale.invert(eventX));
const keys = _.map(this._seriesDataForRendring, el => el.key); const keys = _.map(this._seriesDataForRendring, el => el.key);
const idx = findClosest(keys, mousePoisitionKey); const idx = findClosest(keys, mousePoisitionKey);
return this._seriesDataForRendring[idx]; return this._seriesDataForRendring[idx];
} }
getBarColor(serie: any) {
if(serie.color === undefined) {
return this.getSerieColor(0);
}
return serie.color;
}
onMouseOver(): void { onMouseOver(): void {
this.crosshair.style('display', null); this.crosshair.style('display', null);
this.crosshair.raise(); this.crosshair.raise();
} }
onMouseOut(): void { onMouseOut(): void {
if(this.options.eventsCallbacks !== undefined && this.options.eventsCallbacks.mouseOut !== undefined) { this.options.callbackMouseOut();
this.options.eventsCallbacks.mouseOut();
} else {
console.log('mouse out, but there is no callback');
}
this.crosshair.style('display', 'none'); this.crosshair.style('display', 'none');
} }
@ -272,30 +253,25 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
const event = d3.mouse(this.chartContainer.node()); const event = d3.mouse(this.chartContainer.node());
const eventX = event[0]; const eventX = event[0];
const series = this.getSeriesPointFromMousePosition(eventX); const series = this.getSeriesPointFromMousePosition(eventX);
this.options.callbackContextMenu({
if(this.options.eventsCallbacks !== undefined && this.options.eventsCallbacks.contextMenu !== undefined) { pageX: d3.event.pageX,
this.options.eventsCallbacks.contextMenu({ pageY: d3.event.pageY,
x: d3.event.pageX, xVal: this.state.xScale.invert(eventX),
y: d3.event.pageY,
time: this.xScale.invert(eventX),
series, series,
chartX: eventX chartX: eventX
}); });
} else {
console.log('contextmenu, but there is no callback');
}
} }
get barWidth(): number { get barWidth(): number {
// TODO: here we use first value + timeInterval as bar width. It is not a good idea // TODO: here we use first value + timeInterval as bar width. It is not a good idea
const xAxisStartValue = _.first(this.series[0].datapoints)[0]; const xAxisStartValue = _.first(this.series.visibleSeries[0].datapoints)[0];
let width = this.xScale(xAxisStartValue + this.timeInterval) / 2; let width = this.state.xScale(xAxisStartValue + this.timeInterval) / 2;
if(this.options.barWidth !== undefined) { if(this.options.barOptions.barWidth !== undefined) {
// barWidth now has axis-x dimension // barWidth now has axis-x dimension
width = this.xScale(this.state.getMinValueX() + this.options.barWidth); width = this.state.xScale(this.state.getMinValueX() + this.options.barOptions.barWidth);
} }
let rectColumns = this.visibleSeries.length; let rectColumns = this.series.visibleSeries.length;
if(this.options.stacked === true) { if(this.options.barOptions.stacked === true) {
rectColumns = 1; rectColumns = 1;
} }
return this.updateBarWidthWithBorders(width / rectColumns); return this.updateBarWidthWithBorders(width / rectColumns);
@ -303,11 +279,11 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
updateBarWidthWithBorders(width: number): number { updateBarWidthWithBorders(width: number): number {
let barWidth = width; let barWidth = width;
if(this.options.minBarWidth !== undefined) { if(this.options.barOptions.minBarWidth !== undefined) {
barWidth = Math.max(barWidth, this.options.minBarWidth); barWidth = Math.max(barWidth, this.options.barOptions.minBarWidth);
} }
if(this.options.maxBarWidth !== undefined) { if(this.options.barOptions.maxBarWidth !== undefined) {
barWidth = Math.min(barWidth, this.options.maxBarWidth); barWidth = Math.min(barWidth, this.options.barOptions.maxBarWidth);
} }
return barWidth; return barWidth;
} }
@ -320,8 +296,8 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
} }
getBarPositionX(key: number, idx: number): number { getBarPositionX(key: number, idx: number): number {
let xPosition: number = this.xScale(key); let xPosition: number = this.state.xScale(key);
if(this.options.stacked === false) { if(this.options.barOptions.stacked === false) {
xPosition += idx * this.barWidth; xPosition += idx * this.barWidth;
} }
return xPosition; return xPosition;
@ -329,7 +305,7 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
getBarPositionY(val: number, idx: number, values: number[]): number { getBarPositionY(val: number, idx: number, values: number[]): number {
let yPosition: number = this.barYScale(Math.max(val, 0)); let yPosition: number = this.barYScale(Math.max(val, 0));
if(this.options.stacked === true) { if(this.options.barOptions.stacked === true) {
const previousBarsHeight = _.sum( const previousBarsHeight = _.sum(
_.map(_.range(idx), i => this.getBarHeight(values[i])) _.map(_.range(idx), i => this.getBarHeight(values[i]))
); );
@ -354,15 +330,15 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
} }
getYMaxValue(): number | undefined { getYMaxValue(): number | undefined {
if(this.series === undefined || this.series.length === 0 || this.series[0].datapoints.length === 0) { if(!this.series.isSeriesAvailable) {
return undefined; return undefined;
} }
if(this.options.axis.y !== undefined && this.options.axis.y.range !== undefined) { if(this.options.axis.y.range) {
return _.max(this.options.axis.y.range); return _.max(this.options.axis.y.range);
} }
let maxValue: number; let maxValue: number;
if(this.options.stacked === true) { if(this.options.barOptions.stacked === true) {
if(this.options.matching === true && this.seriesUniqKeys.length > 0) { if(this.options.barOptions.matching === true && this.seriesUniqKeys.length > 0) {
const maxValues = this.seriesForMatching.map(series => { const maxValues = this.seriesForMatching.map(series => {
const valuesColumns = _.map(series, serie => _.map(serie.datapoints, row => row[1])); const valuesColumns = _.map(series, serie => _.map(serie.datapoints, row => row[1]));
const zippedValuesColumn = _.zip(...valuesColumns); const zippedValuesColumn = _.zip(...valuesColumns);
@ -370,14 +346,13 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
}); });
return _.max(maxValues); return _.max(maxValues);
} else { } else {
const valuesColumns = _.map(this.visibleSeries, serie => _.map(serie.datapoints, row => row[1])); const valuesColumns = _.map(this.series.visibleSeries, serie => _.map(serie.datapoints, row => row[1]));
const zippedValuesColumn = _.zip(...valuesColumns); const zippedValuesColumn = _.zip(...valuesColumns);
maxValue = _.max(_.map(zippedValuesColumn, row => _.sum(row))); maxValue = _.max(_.map(zippedValuesColumn, row => _.sum(row)));
} }
} else { } else {
console.log('else')
maxValue = _.max( maxValue = _.max(
this.visibleSeries.map( this.series.visibleSeries.map(
serie => _.maxBy<number[]>(serie.datapoints, dp => dp[1])[0] serie => _.maxBy<number[]>(serie.datapoints, dp => dp[1])[0]
) )
); );
@ -409,4 +384,4 @@ export const VueChartwerkBarChartObject = {
} }
}; };
export { BarTimeSerie, BarOptions, TickOrientation, TimeFormat, AxisFormat }; export { BarSerie, BarOptions, TimeFormat, AxisFormat };

46
src/models/bar_options.ts

@ -0,0 +1,46 @@
import { CoreOptions } from '@chartwerk/core';
import { BarOptions, BarAdditionalOptions } from '../types';
import * as _ from 'lodash';
const BAR_SERIE_DEFAULTS = {
renderBarLabels: false,
stacked: false,
barWidth: undefined,
maxBarWidth: undefined,
minBarWidth: undefined,
maxAnnotationSize: undefined,
minAnnotationSize: undefined,
matching: false,
opacityFormatter: undefined,
annotations: [],
};
export class BarConfig extends CoreOptions<BarOptions> {
constructor(options: BarOptions) {
super(options, BAR_SERIE_DEFAULTS);
}
get barOptions(): BarAdditionalOptions {
return {
renderBarLabels: this._options.renderBarLabels,
stacked: this._options.stacked,
barWidth: this._options.barWidth,
maxBarWidth: this._options.maxBarWidth,
minBarWidth: this._options.minBarWidth,
maxAnnotationSize: this._options.maxAnnotationSize,
minAnnotationSize: this._options.minAnnotationSize,
matching: this._options.matching,
opacityFormatter: this._options.opacityFormatter,
annotations: this._options.annotations,
}
}
// event callbacks
callbackContextMenu(data: any): void {
if(_.has(this._options.eventsCallbacks, 'contextMenu')) {
this._options.eventsCallbacks.contextMenu(data);
}
}
}

15
src/models/bar_series.ts

@ -0,0 +1,15 @@
import { CoreSeries } from '@chartwerk/core';
import { BarSerie } from '../types';
const BAR_SERIE_DEFAULTS = {
matchedKey: undefined,
colorFormatter: undefined
};
export class BarSeries extends CoreSeries<BarSerie> {
constructor(series: BarSerie[]) {
super(series, BAR_SERIE_DEFAULTS);
}
}

33
src/types.ts

@ -1,27 +1,30 @@
import { TimeSerie, Options } from '@chartwerk/core'; import { Serie, Options } from '@chartwerk/core';
export type BarSerieParams = { export type BarSerieParams = {
matchedKey: string; matchedKey: string;
colorFormatter: (serie: BarTimeSerie) => string; colorFormatter: (serie: BarSerie) => string;
} }
export type BarTimeSerie = TimeSerie & Partial<BarSerieParams>; export type BarSerie = Serie & Partial<BarSerieParams>;
export type BarOptionsParams = { export type BarAdditionalOptions = {
renderBarLabels: boolean; renderBarLabels?: boolean;
stacked: boolean; stacked?: boolean;
barWidth: number; // width in x axis unit barWidth?: number; // width in x axis unit
maxBarWidth: number; // in px maxBarWidth?: number; // in px
minBarWidth: number; // in px minBarWidth?: number; // in px
maxAnnotationSize: number; // in px TODO: move to annotaions maxAnnotationSize?: number; // in px TODO: move to annotaions
minAnnotationSize: number; // in px minAnnotationSize?: number; // in px
matching: boolean; matching?: boolean;
opacityFormatter: (data: RowValues) => number; opacityFormatter?: (data: RowValues) => number;
annotations: { annotations?: {
key: string, // matchedKey from series key: string, // matchedKey from series
// TODO: add enum with "triangle" option // TODO: add enum with "triangle" option
color: string, color: string,
}[]; }[];
eventsCallbacks?: {
contextMenu?: (data: any) => void;
} }
export type BarOptions = Options & Partial<BarOptionsParams>; }
export type BarOptions = Options & Partial<BarAdditionalOptions>;
export type RowValues = { export type RowValues = {
key: number, key: number,
values: number[], values: number[],

10
yarn.lock

@ -9,7 +9,7 @@ __metadata:
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "@chartwerk/bar-pod@workspace:." resolution: "@chartwerk/bar-pod@workspace:."
dependencies: dependencies:
"@chartwerk/core": 0.6.3 "@chartwerk/core": latest
css-loader: ^3.4.2 css-loader: ^3.4.2
style-loader: ^1.1.3 style-loader: ^1.1.3
ts-loader: ^6.2.1 ts-loader: ^6.2.1
@ -19,13 +19,13 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@chartwerk/core@npm:0.6.3": "@chartwerk/core@npm:latest":
version: 0.6.3 version: 0.6.5
resolution: "@chartwerk/core@npm:0.6.3" resolution: "@chartwerk/core@npm:0.6.5"
dependencies: dependencies:
d3: ^5.7.2 d3: ^5.7.2
lodash: ^4.14.149 lodash: ^4.14.149
checksum: bb804b1a2339fc19857e5caa07d16ed78fb1b0739878d3f7488e9f8661667ed78ada3a63afd15206bd4210746b50916b253e98f077451cc8d899728ecf08ba50 checksum: 2757ae8be04b84c3624bd807a437d6bf3c67fef0808e3192f0a97ba819627f3b28821628cfefdfabe1951e8b7d0d45d1b9f6ade13cdc4a5bca5e539fc70850df
languageName: node languageName: node
linkType: hard linkType: hard

Loading…
Cancel
Save