@kanaries/graphic-walker 0.2.16 → 0.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/App.d.ts +3 -4
  2. package/dist/assets/viewQuery.worker-ffefc111.js.map +1 -1
  3. package/dist/dataSource/index.d.ts +0 -1
  4. package/dist/fields/encodeFields/singleEncodeEditor.d.ts +4 -4
  5. package/dist/graphic-walker.es.js +29716 -34642
  6. package/dist/graphic-walker.es.js.map +1 -1
  7. package/dist/graphic-walker.umd.js +218 -256
  8. package/dist/graphic-walker.umd.js.map +1 -1
  9. package/dist/interfaces.d.ts +31 -16
  10. package/dist/lib/inferMeta.d.ts +2 -9
  11. package/dist/lib/insights/explainByChildren.d.ts +16 -0
  12. package/dist/lib/insights/explainBySelection.d.ts +5 -0
  13. package/dist/lib/insights/explainValue.d.ts +2 -0
  14. package/dist/lib/insights/utils.d.ts +11 -0
  15. package/dist/lib/interfaces.d.ts +2 -1
  16. package/dist/lib/op/aggregate.d.ts +1 -1
  17. package/dist/lib/op/bin.d.ts +1 -1
  18. package/dist/lib/op/fold.d.ts +1 -1
  19. package/dist/lib/viewQuery.d.ts +1 -2
  20. package/dist/services.d.ts +1 -30
  21. package/dist/store/visualSpecStore.d.ts +1 -2
  22. package/dist/utils/autoMark.d.ts +1 -1
  23. package/dist/utils/dataPrep.d.ts +1 -2
  24. package/dist/vis/react-vega.d.ts +1 -0
  25. package/dist/vis/spec/encode.d.ts +1 -0
  26. package/dist/vis/spec/mark.d.ts +1 -1
  27. package/dist/vis/spec/tooltip.d.ts +4 -0
  28. package/dist/vis/spec/view.d.ts +9 -3
  29. package/package.json +2 -4
  30. package/src/App.tsx +55 -68
  31. package/src/dataSource/index.tsx +0 -17
  32. package/src/fields/aestheticFields.tsx +1 -2
  33. package/src/fields/encodeFields/singleEncodeEditor.tsx +11 -12
  34. package/src/fields/fieldsContext.tsx +1 -0
  35. package/src/interfaces.ts +75 -63
  36. package/src/lib/inferMeta.ts +26 -29
  37. package/src/lib/insights/explainByChildren.ts +50 -0
  38. package/src/lib/insights/explainBySelection.ts +47 -0
  39. package/src/lib/insights/explainValue.ts +30 -0
  40. package/src/lib/insights/utils.ts +21 -0
  41. package/src/lib/interfaces.ts +3 -9
  42. package/src/lib/op/aggregate.ts +1 -1
  43. package/src/lib/op/bin.ts +1 -1
  44. package/src/lib/op/fold.ts +1 -1
  45. package/src/lib/viewQuery.ts +1 -2
  46. package/src/locales/en-US.json +2 -1
  47. package/src/locales/zh-CN.json +2 -1
  48. package/src/renderer/specRenderer.tsx +2 -0
  49. package/src/services.ts +65 -67
  50. package/src/store/visualSpecStore.ts +2 -4
  51. package/src/utils/autoMark.ts +1 -1
  52. package/src/utils/dataPrep.ts +1 -2
  53. package/src/vis/react-vega.tsx +5 -0
  54. package/src/vis/spec/encode.ts +1 -0
  55. package/src/vis/spec/mark.ts +1 -1
  56. package/src/vis/spec/tooltip.ts +16 -0
  57. package/src/vis/spec/view.ts +12 -14
  58. package/dist/assets/explainer.worker-8428eb12.js.map +0 -1
  59. package/dist/insightBoard/index.d.ts +0 -3
  60. package/dist/insightBoard/mainBoard.d.ts +0 -11
  61. package/dist/insightBoard/radioGroupButtons.d.ts +0 -12
  62. package/dist/insightBoard/selectionSpec.d.ts +0 -13
  63. package/dist/insightBoard/std2vegaSpec.d.ts +0 -12
  64. package/dist/insightBoard/utils.d.ts +0 -8
  65. package/dist/insights.d.ts +0 -61
  66. package/src/insightBoard/index.tsx +0 -31
  67. package/src/insightBoard/mainBoard.tsx +0 -224
  68. package/src/insightBoard/radioGroupButtons.tsx +0 -57
  69. package/src/insightBoard/selectionSpec.ts +0 -113
  70. package/src/insightBoard/std2vegaSpec.ts +0 -184
  71. package/src/insightBoard/utils.ts +0 -32
  72. package/src/insights.ts +0 -408
  73. package/src/workers/explainer.worker.js +0 -76
package/src/interfaces.ts CHANGED
@@ -1,19 +1,28 @@
1
- import { StatFuncName } from "visual-insights/build/esm/statistics";
2
- import { AggFC } from 'cube-core/built/types';
3
- import { IAnalyticType, ISemanticType } from 'visual-insights';
4
-
5
1
  export type DeepReadonly<T extends Record<keyof any, any>> = {
6
2
  readonly [K in keyof T]: T[K] extends Record<keyof any, any> ? DeepReadonly<T[K]> : T[K];
7
3
  };
4
+ export type ISemanticType = 'quantitative' | 'nominal' | 'ordinal' | 'temporal';
5
+ export type IDataType = 'number' | 'integer' | 'boolean' | 'date' | 'string';
6
+ export type IAnalyticType = 'dimension' | 'measure';
8
7
 
9
8
  export interface IRow {
10
9
  [key: string]: any;
11
10
  }
12
- /**
13
- * @deprecated
14
- */
15
- export type SemanticType = 'quantitative' | 'nominal' | 'ordinal' | 'temporal';
16
11
 
12
+ export type IAggregator = 'sum' | 'count' | 'max' | 'min' | 'mean' | 'median' | 'variance' | 'stdev';
13
+ export interface Specification {
14
+ position?: string[];
15
+ color?: string[];
16
+ size?: string[];
17
+ shape?: string[];
18
+ opacity?: string[];
19
+ facets?: string[];
20
+ page?: string[];
21
+ filter?: string[];
22
+ highFacets?: string[];
23
+ geomType?: string[];
24
+ aggregate?: boolean;
25
+ }
17
26
  export interface Filters {
18
27
  [key: string]: any[];
19
28
  }
@@ -25,7 +34,7 @@ export interface IMutField {
25
34
  disable?: boolean;
26
35
  semanticType: ISemanticType;
27
36
  analyticType: IAnalyticType;
28
- };
37
+ }
29
38
 
30
39
  export interface IUncertainMutField {
31
40
  fid: string;
@@ -36,21 +45,23 @@ export interface IUncertainMutField {
36
45
  analyticType: IAnalyticType | '?';
37
46
  }
38
47
 
39
-
40
- export type IExpParamter = {
41
- type: 'field';
42
- value: string;
43
- } | {
44
- type: 'value';
45
- value: any;
46
- } | {
47
- type: 'expression';
48
- value: IExpression;
49
- } | {
50
- type: 'constant';
51
- value: any;
52
- }
53
-
48
+ export type IExpParamter =
49
+ | {
50
+ type: 'field';
51
+ value: string;
52
+ }
53
+ | {
54
+ type: 'value';
55
+ value: any;
56
+ }
57
+ | {
58
+ type: 'expression';
59
+ value: IExpression;
60
+ }
61
+ | {
62
+ type: 'constant';
63
+ value: any;
64
+ };
54
65
 
55
66
  export interface IExpression {
56
67
  op: 'bin' | 'log2' | 'log10' | 'one' | 'binCount';
@@ -83,13 +94,6 @@ export interface IViewField extends IField {
83
94
  sort?: 'none' | 'ascending' | 'descending';
84
95
  }
85
96
 
86
- export interface Measure extends IField {
87
- aggregator?: AggFC;
88
- minWidth?: number;
89
- formatter?: (value: number | undefined) => number | string;
90
- [key: string]: any;
91
- }
92
-
93
97
  export interface DataSet {
94
98
  id: string;
95
99
  name: string;
@@ -104,7 +108,20 @@ export interface IFieldNeighbor {
104
108
 
105
109
  export interface IMeasure {
106
110
  key: string;
107
- op: StatFuncName
111
+ op: IAggregator;
112
+ }
113
+
114
+ export interface IPredicate {
115
+ key: string;
116
+ type: "discrete" | "continuous";
117
+ range: Set<any> | [number, number];
118
+ }
119
+
120
+ export interface IExplainProps {
121
+ dataSource: IRow[];
122
+ predicates: IPredicate[];
123
+ viewFields: IField[];
124
+ metas: IField[];
108
125
  }
109
126
 
110
127
  export interface IDataSet {
@@ -119,12 +136,12 @@ export interface IDataSet {
119
136
  export interface IDataSetInfo {
120
137
  name: string;
121
138
  rawFields: IMutField[];
122
- dataSource: IRow[]
139
+ dataSource: IRow[];
123
140
  }
124
141
 
125
142
  export interface IDataSource {
126
143
  id: string;
127
- data: IRow[]
144
+ data: IRow[];
128
145
  }
129
146
 
130
147
  export interface IFilterField extends IViewField {
@@ -149,39 +166,34 @@ export interface DraggableFieldState {
149
166
 
150
167
  export interface IDraggableStateKey {
151
168
  id: keyof DraggableFieldState;
152
- mode: number
153
- }
154
-
155
- export type IFilterRule = {
156
- type: 'range';
157
- value: readonly [number, number];
158
- } | {
159
- type: 'temporal range';
160
- value: readonly [number, number];
161
- } | {
162
- type: 'one of';
163
- value: Set<string | number>;
164
- };
169
+ mode: number;
170
+ }
165
171
 
166
- export const EXPLORATION_TYPES = [
167
- 'none',
168
- 'brush',
169
- 'point',
170
- ] as const;
172
+ export type IFilterRule =
173
+ | {
174
+ type: 'range';
175
+ value: readonly [number, number];
176
+ }
177
+ | {
178
+ type: 'temporal range';
179
+ value: readonly [number, number];
180
+ }
181
+ | {
182
+ type: 'one of';
183
+ value: Set<string | number>;
184
+ };
171
185
 
172
- export const BRUSH_DIRECTIONS = [
173
- 'default',
174
- 'x',
175
- 'y',
176
- ] as const;
186
+ export const EXPLORATION_TYPES = ['none', 'brush', 'point'] as const;
187
+
188
+ export const BRUSH_DIRECTIONS = ['default', 'x', 'y'] as const;
177
189
 
178
190
  export type IStackMode = 'none' | 'stack' | 'normalize';
179
- export type IExplorationType = (typeof EXPLORATION_TYPES)[number];
180
- export type IBrushDirection = (typeof BRUSH_DIRECTIONS)[number];
191
+ export type IExplorationType = typeof EXPLORATION_TYPES[number];
192
+ export type IBrushDirection = typeof BRUSH_DIRECTIONS[number];
181
193
 
182
194
  export interface IVisualConfig {
183
195
  defaultAggregated: boolean;
184
- geoms: string[];
196
+ geoms: string[];
185
197
  stack: IStackMode;
186
198
  showActions: boolean;
187
199
  interactiveScale: boolean;
@@ -190,7 +202,7 @@ export interface IVisualConfig {
190
202
  mode: 'auto' | 'fixed';
191
203
  width: number;
192
204
  height: number;
193
- }
205
+ };
194
206
  exploration: {
195
207
  mode: IExplorationType;
196
208
  /** works when mode is 'brush' */
@@ -207,8 +219,8 @@ export interface IVisSpec {
207
219
 
208
220
  export enum ISegmentKey {
209
221
  vis = 'vis',
210
- data = 'data'
222
+ data = 'data',
211
223
  }
212
224
 
213
225
  export type IThemeKey = 'vega' | 'g2';
214
- export type IDarkMode = 'media' | 'light' | 'dark';
226
+ export type IDarkMode = 'media' | 'light' | 'dark';
@@ -1,5 +1,4 @@
1
- import { IAnalyticType, ISemanticType, UnivariateSummary } from "visual-insights";
2
- import { IMutField, IRow, IUncertainMutField } from "../interfaces";
1
+ import { IAnalyticType, IMutField, IRow, ISemanticType, IUncertainMutField } from '../interfaces';
3
2
 
4
3
  const COMMON_TIME_FORMAT: RegExp[] = [
5
4
  /^\d{4}-\d{2}-\d{2}$/, // YYYY-MM-DD
@@ -8,13 +7,13 @@ const COMMON_TIME_FORMAT: RegExp[] = [
8
7
  /^\d{4}\/\d{2}\/\d{2}$/, // YYYY/MM/DD
9
8
  /^\d{4}\.\d{2}\.\d{2}$/, // YYYY.MM.DD
10
9
  /^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}$/, // YYYY-MM-DD HH:MM:SS
11
- /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/ // YYYY-MM-DDTHH:MM:SS (ISO-8601)
10
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/, // YYYY-MM-DDTHH:MM:SS (ISO-8601)
12
11
  ];
13
12
 
14
13
  /**
15
14
  * check if this array is a date time array based on some common date format
16
15
  * @param data string array
17
- * @returns
16
+ * @returns
18
17
  */
19
18
  export function isDateTimeArray(data: string[]): boolean {
20
19
  let isDateTime = true;
@@ -34,6 +33,19 @@ export function isDateTimeArray(data: string[]): boolean {
34
33
  return isDateTime;
35
34
  }
36
35
 
36
+ export function isNumericArray(data: any[]): boolean {
37
+ return data.every((item) => {
38
+ // Check if the item is already a number
39
+ if (typeof item === 'number') {
40
+ return true;
41
+ }
42
+
43
+ // Check if the item can be converted into a number
44
+ const number = parseFloat(item);
45
+ return !isNaN(number) && isFinite(item);
46
+ });
47
+ }
48
+
37
49
  function inferAnalyticTypeFromSemanticType(semanticType: ISemanticType): IAnalyticType {
38
50
  switch (semanticType) {
39
51
  case 'quantitative':
@@ -43,37 +55,22 @@ function inferAnalyticTypeFromSemanticType(semanticType: ISemanticType): IAnalyt
43
55
  }
44
56
  }
45
57
 
46
- /**
47
- * 这里目前暂时包一层,是为了解耦具体的推断实现。后续这里要调整推断的逻辑。
48
- * 需要讨论这一层是否和交互层有关,如果没有关系,这一层包裹可以不存在这里,而是在visual-insights中。
49
- * @param data 原始数据
50
- * @param fid 字段id
51
- * @returns semantic type 列表
52
- */
53
58
  export function inferSemanticType(data: IRow[], fid: string): ISemanticType {
54
- let st = UnivariateSummary.getFieldType(data, fid);
59
+ const values = data.map((row) => row[fid]);
60
+
61
+ let st: ISemanticType = isNumericArray(values) ? 'quantitative' : 'nominal';
55
62
  if (st === 'nominal') {
56
63
  if (isDateTimeArray(data.map((row) => `${row[fid]}`))) st = 'temporal';
57
- } else if (st === 'ordinal') {
58
- const valueSet: Set<number> = new Set();
59
- let _max = -Infinity;
60
- let _min = Infinity;
61
- for (let v of valueSet) {
62
- _max = Math.max(_max, v);
63
- _min = Math.max(_min, v);
64
- }
65
- if (_max - _min + 1 !== valueSet.size) {
66
- st = 'quantitative';
67
- }
68
64
  }
69
65
  return st;
70
66
  }
71
67
 
72
- export function inferMeta (props: { dataSource: IRow[]; fields: IUncertainMutField[] }): IMutField[] {
68
+ export function inferMeta(props: { dataSource: IRow[]; fields: IUncertainMutField[] }): IMutField[] {
73
69
  const { dataSource, fields } = props;
74
- const finalFieldMetas: IMutField[] = []
70
+ const finalFieldMetas: IMutField[] = [];
75
71
  for (let field of fields) {
76
- let semanticType: ISemanticType = field.semanticType === '?' ? inferSemanticType(dataSource, field.fid) : field.semanticType;
72
+ let semanticType: ISemanticType =
73
+ field.semanticType === '?' ? inferSemanticType(dataSource, field.fid) : field.semanticType;
77
74
  let analyticType: IAnalyticType = inferAnalyticTypeFromSemanticType(semanticType);
78
75
 
79
76
  finalFieldMetas.push({
@@ -82,7 +79,7 @@ export function inferMeta (props: { dataSource: IRow[]; fields: IUncertainMutFie
82
79
  name: field.name ? field.name : field.fid,
83
80
  analyticType,
84
81
  semanticType,
85
- })
82
+ });
86
83
  }
87
- return finalFieldMetas
88
- }
84
+ return finalFieldMetas;
85
+ }
@@ -0,0 +1,50 @@
1
+ import { IMeasure, IRow } from '../../interfaces';
2
+ import { IPredicate, checkChildOutlier, checkMajorFactor, filterByPredicates } from '../../utils';
3
+ import { aggregate } from '../op/aggregate';
4
+
5
+ export function explainByChildren(
6
+ dataSource: IRow[],
7
+ predicates: IPredicate[],
8
+ dimensions: string[],
9
+ measures: IMeasure[]
10
+ ) {
11
+ // 1. find most relative dimensions(topK)
12
+ // 2. for each dimension, we check all the dim member in it. find the member whos distribution is most close to current one.
13
+ // here we do not nomorlize all the dim member's distribution, we use the relative distribution instead.
14
+ // 3. the dim member we found can be used to explain current one as major factor.
15
+ // const predicates: IPredicate[] = selection === 'all' ? [] : getPredicates(selection, dimensions, []);
16
+ const viewData = aggregate(dataSource, {
17
+ groupBy: dimensions,
18
+ op: 'aggregate',
19
+ agg: Object.fromEntries(measures.map((mea) => [mea.key, mea.op])),
20
+ });
21
+ const measureIds = measures.map((m) => m.key);
22
+ const parentData = filterByPredicates(viewData, predicates);
23
+
24
+ const majorList: Array<{ key: string; score: number; dimensions: string[]; measures: IMeasure[] }> = [];
25
+ const outlierList: Array<{ key: string; score: number; dimensions: string[]; measures: IMeasure[] }> = [];
26
+ for (let extendDim of dimensions) {
27
+ const data = aggregate(dataSource, {
28
+ groupBy: dimensions.concat(extendDim),
29
+ op: 'aggregate',
30
+ agg: Object.fromEntries(measures.map((mea) => [mea.key, mea.op])),
31
+ });
32
+ let groups: Map<any, IRow[]> = new Map();
33
+ for (let record of data) {
34
+ if (!groups.has(record[extendDim])) {
35
+ groups.set(record[extendDim], []);
36
+ }
37
+ groups.get(record[extendDim])?.push(record);
38
+ }
39
+ const { majorKey, majorSum } = checkMajorFactor(parentData, groups, dimensions, measureIds);
40
+ majorList.push({ key: majorKey, score: majorSum, dimensions: [extendDim], measures });
41
+ const { outlierKey, outlierSum } = checkChildOutlier(parentData, groups, dimensions, measureIds);
42
+ outlierList.push({ key: outlierKey, score: outlierSum, dimensions: [extendDim], measures });
43
+ }
44
+ majorList.sort((a, b) => a.score - b.score);
45
+ outlierList.sort((a, b) => b.score - a.score);
46
+ return {
47
+ majorList,
48
+ outlierList,
49
+ };
50
+ }
@@ -0,0 +1,47 @@
1
+ import { IExplainProps, IField } from '../../interfaces';
2
+ import { filterByPredicates } from '../../utils';
3
+ import { compareDistribution, normalizeWithParent } from '../../utils/normalization';
4
+ import { aggregate } from '../op/aggregate';
5
+ import { complementaryFields, groupByAnalyticTypes, meaList2AggProps } from './utils';
6
+
7
+ export function explainBySelection(props: IExplainProps) {
8
+ const { metas, dataSource, viewFields, predicates } = props;
9
+ const { dimensions: dimsInView, measures: measInView } = groupByAnalyticTypes(viewFields);
10
+ const complementaryDimensions = complementaryFields({
11
+ all: metas.filter((f) => f.analyticType === 'dimension'),
12
+ selection: dimsInView,
13
+ });
14
+ const outlierList: Array<{ score: number; viiewFields: IField[] }> = complementaryDimensions.map(extendDim => {
15
+ const overallData = aggregate(dataSource, {
16
+ groupBy: [extendDim.fid],
17
+ op: 'aggregate',
18
+ agg: meaList2AggProps(measInView),
19
+ });
20
+ const viewData = aggregate(dataSource, {
21
+ groupBy: dimsInView.map((f) => f.fid),
22
+ op: 'aggregate',
23
+ agg: meaList2AggProps(measInView),
24
+ });
25
+ const subData = filterByPredicates(viewData, predicates);
26
+
27
+ let outlierNormalization = normalizeWithParent(
28
+ subData,
29
+ overallData,
30
+ measInView.map((mea) => mea.fid),
31
+ false
32
+ );
33
+
34
+ let outlierScore = compareDistribution(
35
+ outlierNormalization.normalizedData,
36
+ outlierNormalization.normalizedParentData,
37
+ [extendDim.fid],
38
+ measInView.map((mea) => mea.fid)
39
+ );
40
+ return {
41
+ viiewFields: measInView.concat(extendDim),
42
+ score: outlierScore,
43
+ }
44
+ }).sort((a, b) => b.score - a.score)
45
+
46
+ return outlierList;
47
+ }
@@ -0,0 +1,30 @@
1
+ import { IAggregator, IExplainProps } from '../../interfaces';
2
+ import { filterByPredicates } from '../../utils';
3
+ import { aggregate } from '../op/aggregate';
4
+ import { complementaryFields, groupByAnalyticTypes } from './utils';
5
+
6
+ export function explainValue(props: IExplainProps): number[] {
7
+ const { viewFields, dataSource, predicates } = props;
8
+ const { dimensions: dimsInView, measures: measInView } = groupByAnalyticTypes(viewFields);
9
+ const viewData = aggregate(dataSource, {
10
+ groupBy: dimsInView.map((f) => f.fid),
11
+ op: 'aggregate',
12
+ agg: Object.fromEntries(measInView.map((mea) => [mea.fid, (mea.aggName ?? 'sum') as IAggregator])),
13
+ });
14
+ const selection = filterByPredicates(viewData, predicates);
15
+ const cmps: number[] = [];
16
+ for (let mea of measInView) {
17
+ const values = viewData.map((r) => r[mea.fid]).sort((a, b) => a - b);
18
+ const selectionValues = selection.map((r) => r[mea.fid]);
19
+ const lowerBoundary: number = values[Math.floor(values.length * 0.15)];
20
+ const higherBoundary: number = values[Math.min(Math.ceil(values.length * 0.85), values.length - 1)];
21
+ if (selectionValues.some((v) => v >= higherBoundary)) {
22
+ cmps.push(1);
23
+ } else if (selectionValues.some((v) => v <= lowerBoundary)) {
24
+ cmps.push(-1);
25
+ } else {
26
+ cmps.push(0);
27
+ }
28
+ }
29
+ return cmps;
30
+ }
@@ -0,0 +1,21 @@
1
+ import { IAggregator, IField } from '../../interfaces';
2
+ import { IAggQuery } from '../interfaces';
3
+
4
+ export function groupByAnalyticTypes(fields: IField[]) {
5
+ const dimensions = fields.filter((f) => f.analyticType === 'dimension');
6
+ const measures = fields.filter((f) => f.analyticType === 'measure');
7
+ return {
8
+ dimensions,
9
+ measures,
10
+ };
11
+ }
12
+
13
+ export function meaList2AggProps(measures: IField[]): IAggQuery['agg'] {
14
+ return Object.fromEntries(measures.map((mea) => [mea.fid, (mea.aggName ?? 'sum') as IAggregator]));
15
+ }
16
+
17
+ export function complementaryFields(props: { selection: IField[]; all: IField[] }): IField[] {
18
+ return props.all
19
+ .filter((f) => f.analyticType === 'dimension')
20
+ .filter((f) => !props.selection.find((vf) => vf.fid === f.fid));
21
+ }
@@ -1,16 +1,10 @@
1
+ import { IAggregator } from "../interfaces";
2
+
1
3
  export interface IAggQuery {
2
4
  op: 'aggregate';
3
5
  groupBy: string[];
4
6
  agg: {
5
- [field: string]:
6
- | 'sum'
7
- | 'count'
8
- | 'max'
9
- | 'min'
10
- | 'mean'
11
- | 'median'
12
- | 'variance'
13
- | 'stdev';
7
+ [field: string]: IAggregator;
14
8
  };
15
9
  }
16
10
 
@@ -1,4 +1,4 @@
1
- import { IRow } from "visual-insights";
1
+ import { IRow } from "../../interfaces";
2
2
  import { IAggQuery } from "../interfaces";
3
3
  import { sum, mean, median, stdev, variance, max, min, count } from "./stat";
4
4
 
package/src/lib/op/bin.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IRow } from "visual-insights";
1
+ import { IRow } from "../../interfaces";
2
2
  import { IBinQuery } from "../interfaces";
3
3
 
4
4
  export function bin (dataSource: IRow[], query: IBinQuery): IRow[] {
@@ -1,4 +1,4 @@
1
- import { IRow } from "visual-insights";
1
+ import { IRow } from "../../interfaces";
2
2
  import { IFoldQuery } from "../interfaces";
3
3
 
4
4
  export function fold (data: IRow[], query: IFoldQuery): IRow[] {
@@ -1,5 +1,4 @@
1
- import { IRow } from "visual-insights";
2
- import { IMutField } from "../interfaces";
1
+ import { IMutField, IRow } from "../interfaces";
3
2
  import { aggregate } from "./op/aggregate";
4
3
  import { fold } from "./op/fold";
5
4
  import { IAggQuery, IBinQuery, IFoldQuery, IRawQuery } from "./interfaces";
@@ -58,7 +58,8 @@
58
58
  "shape": "Shape",
59
59
  "theta": "Angle",
60
60
  "radius": "Radius",
61
- "filters": "Filters"
61
+ "filters": "Filters",
62
+ "details": "Details"
62
63
  },
63
64
  "aggregator": {
64
65
  "sum": "Sum",
@@ -58,7 +58,8 @@
58
58
  "shape": "形状",
59
59
  "theta": "角度",
60
60
  "radius": "半径",
61
- "filters": "筛选器"
61
+ "filters": "筛选器",
62
+ "details": "信息"
62
63
  },
63
64
  "aggregator": {
64
65
  "sum": "求和",
@@ -31,6 +31,7 @@ const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
31
31
  const theta = draggableFieldState.theta;
32
32
  const radius = draggableFieldState.radius;
33
33
  const sizeChannel = draggableFieldState.size;
34
+ const details = draggableFieldState.details;
34
35
 
35
36
  const rowLeftFacetFields = useMemo(() => rows.slice(0, -1).filter((f) => f.analyticType === 'dimension'), [rows]);
36
37
  const colLeftFacetFields = useMemo(
@@ -102,6 +103,7 @@ const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
102
103
  shape={shape[0]}
103
104
  opacity={opacity[0]}
104
105
  size={sizeChannel[0]}
106
+ details={details}
105
107
  showActions={showActions}
106
108
  width={size.width - 12 * 4}
107
109
  height={size.height - 12 * 4}