@kanaries/graphic-walker 0.2.7 → 0.2.8

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.
@@ -112,11 +112,15 @@ export declare type IFilterRule = {
112
112
  type: 'one of';
113
113
  value: Set<string | number>;
114
114
  };
115
+ export declare const EXPLORATION_TYPES: readonly ["none", "brush", "point"];
116
+ export declare const BRUSH_DIRECTIONS: readonly ["default", "x", "y"];
115
117
  export declare type IStackMode = 'none' | 'stack' | 'normalize';
118
+ export declare type IExplorationType = (typeof EXPLORATION_TYPES)[number];
119
+ export declare type IBrushDirection = (typeof BRUSH_DIRECTIONS)[number];
116
120
  export interface IVisualConfig {
117
121
  defaultAggregated: boolean;
118
122
  geoms: string[];
119
- stack: 'none' | 'stack' | 'normalize';
123
+ stack: IStackMode;
120
124
  showActions: boolean;
121
125
  interactiveScale: boolean;
122
126
  sorted: 'none' | 'ascending' | 'descending';
@@ -125,6 +129,11 @@ export interface IVisualConfig {
125
129
  width: number;
126
130
  height: number;
127
131
  };
132
+ exploration: {
133
+ mode: IExplorationType;
134
+ /** works when mode is 'brush' */
135
+ brushDirection: IBrushDirection;
136
+ };
128
137
  }
129
138
  export interface IVisSpec {
130
139
  readonly visId: string;
@@ -89,6 +89,7 @@ export declare class VizSpecStore {
89
89
  width?: number;
90
90
  height?: number;
91
91
  }): void;
92
+ setExploration(value: Partial<IVisualConfig['exploration']>): void;
92
93
  reorderField(stateKey: keyof DraggableFieldState, sourceIndex: number, destinationIndex: number): void;
93
94
  moveField(sourceKey: keyof DraggableFieldState, sourceIndex: number, destinationKey: keyof DraggableFieldState, destinationIndex: number): void;
94
95
  removeField(sourceKey: keyof DraggableFieldState, sourceIndex: number): void;
@@ -4,7 +4,9 @@ export declare function dumpsGWPureSpec(list: VisSpecWithHistory[]): IVisSpec[];
4
4
  export declare function parseGWPureSpec(list: IVisSpec[]): VisSpecWithHistory[];
5
5
  interface IStoInfo {
6
6
  datasets: IDataSet[];
7
- specList: IVisSpec[];
7
+ specList: ({
8
+ [K in keyof IVisSpec]: K extends 'config' ? Partial<IVisSpec[K]> : IVisSpec[K];
9
+ })[];
8
10
  dataSources: IDataSource[];
9
11
  }
10
12
  export declare function stringifyGWContent(info: IStoInfo): string;
@@ -19,6 +19,29 @@ interface ReactVegaProps {
19
19
  width: number;
20
20
  height: number;
21
21
  onGeomClick?: (values: any, e: any) => void;
22
+ selectEncoding: SingleViewProps['selectEncoding'];
23
+ brushEncoding: SingleViewProps['brushEncoding'];
24
+ }
25
+ interface SingleViewProps {
26
+ x: IViewField;
27
+ y: IViewField;
28
+ color: IViewField;
29
+ opacity: IViewField;
30
+ size: IViewField;
31
+ shape: IViewField;
32
+ xOffset: IViewField;
33
+ yOffset: IViewField;
34
+ row: IViewField;
35
+ column: IViewField;
36
+ theta: IViewField;
37
+ radius: IViewField;
38
+ defaultAggregated: boolean;
39
+ stack: IStackMode;
40
+ geomType: string;
41
+ enableCrossFilter: boolean;
42
+ asCrossFilterTrigger: boolean;
43
+ selectEncoding: 'default' | 'none';
44
+ brushEncoding: 'x' | 'y' | 'default' | 'none';
22
45
  }
23
46
  declare const ReactVega: React.FC<ReactVegaProps>;
24
47
  export default ReactVega;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanaries/graphic-walker",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "scripts": {
5
5
  "dev:front_end": "vite --host",
6
6
  "dev": "npm run dev:front_end",
package/src/interfaces.ts CHANGED
@@ -129,13 +129,26 @@ export type IFilterRule = {
129
129
  value: Set<string | number>;
130
130
  };
131
131
 
132
+ export const EXPLORATION_TYPES = [
133
+ 'none',
134
+ 'brush',
135
+ 'point',
136
+ ] as const;
137
+
138
+ export const BRUSH_DIRECTIONS = [
139
+ 'default',
140
+ 'x',
141
+ 'y',
142
+ ] as const;
132
143
 
133
144
  export type IStackMode = 'none' | 'stack' | 'normalize';
145
+ export type IExplorationType = (typeof EXPLORATION_TYPES)[number];
146
+ export type IBrushDirection = (typeof BRUSH_DIRECTIONS)[number];
134
147
 
135
148
  export interface IVisualConfig {
136
149
  defaultAggregated: boolean;
137
150
  geoms: string[];
138
- stack: 'none' | 'stack' | 'normalize';
151
+ stack: IStackMode;
139
152
  showActions: boolean;
140
153
  interactiveScale: boolean;
141
154
  sorted: 'none' | 'ascending' | 'descending';
@@ -144,6 +157,11 @@ export interface IVisualConfig {
144
157
  width: number;
145
158
  height: number;
146
159
  }
160
+ exploration: {
161
+ mode: IExplorationType;
162
+ /** works when mode is 'brush' */
163
+ brushDirection: IBrushDirection;
164
+ };
147
165
  }
148
166
 
149
167
  export interface IVisSpec {
@@ -30,6 +30,18 @@
30
30
  "auto": "Auto",
31
31
  "fixed": "Fixed"
32
32
  },
33
+ "exploration_mode": {
34
+ "__enum__": "Exploration Mode",
35
+ "none": "Off",
36
+ "brush": "Brush",
37
+ "point": "Point"
38
+ },
39
+ "brush_mode": {
40
+ "__enum__": "Brush Direction",
41
+ "default": "Both",
42
+ "x": "X-Only",
43
+ "y": "Y-Only"
44
+ },
33
45
  "draggable_key": {
34
46
  "fields": "Fields",
35
47
  "columns": "Columns",
@@ -24,6 +24,18 @@
24
24
  "auto": "自动",
25
25
  "fixed": "固定"
26
26
  },
27
+ "exploration_mode": {
28
+ "__enum__": "探索交互",
29
+ "none": "关",
30
+ "brush": "范围",
31
+ "point": "目标"
32
+ },
33
+ "brush_mode": {
34
+ "__enum__": "框选方向",
35
+ "default": "所有",
36
+ "x": "仅 X 轴",
37
+ "y": "仅 Y 轴"
38
+ },
27
39
  "stack_mode": {
28
40
  "__enum__": "堆叠模式",
29
41
  "none": "关闭",
@@ -10,7 +10,7 @@ import ReactVega from '../vis/react-vega';
10
10
  const ReactiveRenderer: React.FC = props => {
11
11
  const { vizStore, commonStore } = useGlobalStore();
12
12
  const { draggableFieldState, visualConfig } = vizStore;
13
- const { geoms, interactiveScale, defaultAggregated, stack, showActions, size } = visualConfig;
13
+ const { geoms, interactiveScale, defaultAggregated, stack, showActions, size, exploration } = visualConfig;
14
14
  const { currentDataset } = commonStore;
15
15
  const { filters } = draggableFieldState;
16
16
 
@@ -27,13 +27,17 @@ const ReactiveRenderer: React.FC = props => {
27
27
  const colLeftFacetFields = columns.slice(0, -1).filter(f => f.analyticType === 'dimension');
28
28
 
29
29
  const hasFacet = rowLeftFacetFields.length > 0 || colLeftFacetFields.length > 0;
30
+
31
+ const shouldTriggerMenu = exploration.mode === 'none';
30
32
 
31
- const onGeomClick = useCallback((values: any, e: any) => {
32
- runInAction(() => {
33
- commonStore.showEmbededMenu([e.pageX, e.pageY])
34
- commonStore.setFilters(values);
35
- })
36
- }, [])
33
+ const handleGeomClick = useCallback((values: any, e: any) => {
34
+ if (shouldTriggerMenu) {
35
+ runInAction(() => {
36
+ commonStore.showEmbededMenu([e.pageX, e.pageY])
37
+ commonStore.setFilters(values);
38
+ });
39
+ }
40
+ }, [shouldTriggerMenu]);
37
41
 
38
42
  // apply filters
39
43
  const { dataSource } = currentDataset;
@@ -93,10 +97,12 @@ const ReactiveRenderer: React.FC = props => {
93
97
  shape={shape[0]}
94
98
  opacity={opacity[0]}
95
99
  size={sizeChannel[0]}
96
- onGeomClick={onGeomClick}
97
100
  showActions={showActions}
98
101
  width={size.width - 12 * 4}
99
102
  height={size.height - 12 * 4}
103
+ brushEncoding={exploration.mode === 'brush' ? exploration.brushDirection : 'none'}
104
+ selectEncoding={exploration.mode === 'point' ? 'default' : 'none'}
105
+ onGeomClick={handleGeomClick}
100
106
  />
101
107
  </Resizable>
102
108
  }
@@ -2,7 +2,7 @@ import { IReactionDisposer, makeAutoObservable, observable, reaction, toJS } fro
2
2
  import produce from 'immer';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
4
  import { Specification } from "visual-insights";
5
- import { DataSet, DraggableFieldState, IFilterRule, IViewField, IVisualConfig } from "../interfaces";
5
+ import { DataSet, DraggableFieldState, IFilterRule, IViewField, IVisSpec, IVisualConfig } from "../interfaces";
6
6
  import { CHANNEL_LIMIT, GEMO_TYPES, MetaFieldKeys } from "../config";
7
7
  import { makeBinField, makeLogField } from "../utils/normalization";
8
8
  import { VisSpecWithHistory } from "../models/visSpecHistory";
@@ -69,7 +69,11 @@ function initVisualConfig (): IVisualConfig {
69
69
  mode: 'auto',
70
70
  width: 320,
71
71
  height: 200
72
- }
72
+ },
73
+ exploration: {
74
+ mode: 'brush',
75
+ brushDirection: 'default',
76
+ },
73
77
  }
74
78
  }
75
79
 
@@ -77,6 +81,16 @@ type DeepReadonly<T extends Record<keyof any, any>> = {
77
81
  readonly [K in keyof T]: T[K] extends Record<keyof any, any> ? DeepReadonly<T[K]> : T[K];
78
82
  };
79
83
 
84
+ const forwardVisualConfigs = (backwards: ReturnType<typeof parseGWContent>['specList']): IVisSpec[] => {
85
+ return backwards.map(content => ({
86
+ ...content,
87
+ config: {
88
+ ...initVisualConfig(),
89
+ ...content.config,
90
+ },
91
+ }));
92
+ };
93
+
80
94
 
81
95
  export class VizSpecStore {
82
96
  // public fields: IViewField[] = [];
@@ -363,6 +377,16 @@ export class VizSpecStore {
363
377
  config.size.height = height;
364
378
  });
365
379
  }
380
+ public setExploration(value: Partial<IVisualConfig['exploration']>) {
381
+ this.useMutable(({ config }) => {
382
+ if (value.mode) {
383
+ config.exploration.mode = value.mode;
384
+ }
385
+ if (value.brushDirection) {
386
+ config.exploration.brushDirection = value.brushDirection;
387
+ }
388
+ });
389
+ }
366
390
  public reorderField(stateKey: keyof DraggableFieldState, sourceIndex: number, destinationIndex: number) {
367
391
  if (MetaFieldKeys.includes(stateKey)) return;
368
392
  if (sourceIndex === destinationIndex) return;
@@ -580,7 +604,8 @@ export class VizSpecStore {
580
604
  this.commonStore.datasets = content.datasets;
581
605
  this.commonStore.dataSources = content.dataSources;
582
606
  this.commonStore.dsIndex = Math.max(content.datasets.length - 1, 0);
583
- this.visList = parseGWPureSpec(content.specList)
607
+ // 补上初始化新版本特性
608
+ this.visList = parseGWPureSpec(forwardVisualConfigs(content.specList));
584
609
  this.visIndex = 0;
585
610
  }
586
611
  }
package/src/utils/save.ts CHANGED
@@ -12,7 +12,10 @@ export function parseGWPureSpec (list: IVisSpec[]): VisSpecWithHistory[] {
12
12
 
13
13
  interface IStoInfo {
14
14
  datasets: IDataSet[];
15
- specList: IVisSpec[];
15
+ specList: ({
16
+ /** 由于 gw 内部实现暂时未锁版本,这里获取到的信息可能会与当前实例内容有偏差,需要用初始值合入 */
17
+ [K in keyof IVisSpec]: K extends 'config' ? Partial<IVisSpec[K]> : IVisSpec[K];
18
+ })[];
16
19
  dataSources: IDataSource[]
17
20
  }
18
21