@kanaries/graphic-walker 0.2.15 → 0.2.16

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 (97) hide show
  1. package/dist/App.d.ts +2 -0
  2. package/dist/assets/explainer.worker-8428eb12.js.map +1 -1
  3. package/dist/assets/transform.worker-5d54ff09.js.map +1 -0
  4. package/dist/assets/viewQuery.worker-ffefc111.js.map +1 -0
  5. package/dist/components/codeExport/index.d.ts +3 -0
  6. package/dist/components/loadingLayer.d.ts +2 -0
  7. package/dist/components/tabs/defaultTab.d.ts +1 -0
  8. package/dist/components/tabs/editableTab.d.ts +1 -2
  9. package/dist/dataSource/dataSelection/config.d.ts +1 -0
  10. package/dist/dataSource/dataSelection/utils.d.ts +2 -0
  11. package/dist/datasets/tmp/test.json +1 -0
  12. package/dist/graphic-walker.es.js +23081 -22577
  13. package/dist/graphic-walker.es.js.map +1 -1
  14. package/dist/graphic-walker.umd.js +130 -130
  15. package/dist/graphic-walker.umd.js.map +1 -1
  16. package/dist/index.d.ts +3 -3
  17. package/dist/interfaces.d.ts +21 -1
  18. package/dist/lib/execExp.d.ts +8 -0
  19. package/dist/lib/interfaces.d.ts +22 -0
  20. package/dist/lib/op/aggregate.d.ts +3 -0
  21. package/dist/lib/op/bin.d.ts +3 -0
  22. package/dist/lib/op/fold.d.ts +3 -0
  23. package/dist/lib/op/stat.d.ts +8 -0
  24. package/dist/lib/viewQuery.d.ts +5 -0
  25. package/dist/models/visSpecHistory.d.ts +2 -0
  26. package/dist/renderer/index.d.ts +8 -7
  27. package/dist/renderer/specRenderer.d.ts +13 -0
  28. package/dist/services.d.ts +4 -1
  29. package/dist/store/commonStore.d.ts +6 -0
  30. package/dist/store/index.d.ts +3 -2
  31. package/dist/store/visualSpecStore.d.ts +11 -4
  32. package/dist/utils/dataPrep.d.ts +2 -0
  33. package/dist/utils/index.d.ts +3 -5
  34. package/dist/utils/save.d.ts +1 -2
  35. package/dist/vis/react-vega.d.ts +1 -22
  36. package/dist/vis/spec/aggregate.d.ts +4 -0
  37. package/dist/vis/spec/encode.d.ts +19 -0
  38. package/dist/vis/spec/field.d.ts +2 -0
  39. package/dist/vis/spec/mark.d.ts +7 -0
  40. package/dist/vis/spec/stack.d.ts +4 -0
  41. package/dist/vis/spec/view.d.ts +67 -0
  42. package/dist/workers/transform.d.ts +2 -0
  43. package/package.json +4 -3
  44. package/src/App.tsx +5 -2
  45. package/src/components/codeExport/index.tsx +114 -0
  46. package/src/components/dataTable/index.tsx +10 -10
  47. package/src/components/loadingLayer.tsx +7 -0
  48. package/src/components/tabs/defaultTab.tsx +4 -2
  49. package/src/components/tabs/editableTab.tsx +74 -39
  50. package/src/dataSource/dataSelection/config.ts +11 -0
  51. package/src/dataSource/dataSelection/csvData.tsx +71 -39
  52. package/src/dataSource/dataSelection/gwFile.tsx +2 -2
  53. package/src/dataSource/dataSelection/utils.ts +28 -0
  54. package/src/dataSource/utils.ts +8 -3
  55. package/src/fields/datasetFields/meaFields.tsx +12 -4
  56. package/src/index.css +4 -4
  57. package/src/index.tsx +22 -22
  58. package/src/interfaces.ts +26 -2
  59. package/src/lib/execExp.ts +147 -0
  60. package/src/lib/interfaces.ts +39 -0
  61. package/src/lib/op/aggregate.ts +49 -0
  62. package/src/lib/op/bin.ts +25 -0
  63. package/src/lib/op/fold.ts +17 -0
  64. package/src/lib/op/stat.ts +46 -0
  65. package/src/lib/viewQuery.ts +23 -0
  66. package/src/locales/en-US.json +4 -2
  67. package/src/locales/i18n.ts +0 -1
  68. package/src/locales/ja-JP.json +4 -2
  69. package/src/locales/zh-CN.json +4 -2
  70. package/src/main.tsx +1 -1
  71. package/src/models/visSpecHistory.ts +14 -0
  72. package/src/renderer/index.tsx +58 -126
  73. package/src/renderer/specRenderer.tsx +119 -0
  74. package/src/segments/segmentNav.tsx +3 -16
  75. package/src/segments/visNav.tsx +17 -6
  76. package/src/services.ts +37 -1
  77. package/src/store/commonStore.ts +14 -9
  78. package/src/store/index.tsx +11 -4
  79. package/src/store/visualSpecStore.ts +89 -50
  80. package/src/utils/dataPrep.ts +24 -0
  81. package/src/utils/index.ts +16 -17
  82. package/src/utils/normalization.ts +3 -1
  83. package/src/utils/save.ts +1 -2
  84. package/src/vis/react-vega.tsx +4 -340
  85. package/src/vis/spec/aggregate.ts +13 -0
  86. package/src/vis/spec/encode.ts +69 -0
  87. package/src/vis/spec/field.ts +10 -0
  88. package/src/vis/spec/mark.ts +30 -0
  89. package/src/vis/spec/stack.ts +11 -0
  90. package/src/vis/spec/view.ts +138 -0
  91. package/src/vis/theme.ts +12 -0
  92. package/src/visualSettings/index.tsx +10 -1
  93. package/src/workers/transform.ts +12 -0
  94. package/src/workers/transform.worker.js +13 -0
  95. package/src/workers/viewQuery.worker.js +16 -0
  96. package/dist/dataSource/pannel.d.ts +0 -5
  97. package/src/dataSource/pannel.tsx +0 -71
@@ -0,0 +1,138 @@
1
+ import { ISemanticType } from 'visual-insights';
2
+ import { IStackMode, IViewField } from '../../interfaces';
3
+ import { autoMark } from './mark';
4
+ import { NULL_FIELD } from './field';
5
+ import { channelAggregate } from './aggregate';
6
+ import { IEncodeProps, channelEncode } from './encode';
7
+ import { channelStack } from './stack'
8
+
9
+ const BRUSH_SIGNAL_NAME = '__gw_brush__';
10
+ const POINT_SIGNAL_NAME = '__gw_point__';
11
+ export interface SingleViewProps extends IEncodeProps {
12
+
13
+ defaultAggregated: boolean;
14
+ stack: IStackMode;
15
+ enableCrossFilter: boolean;
16
+ asCrossFilterTrigger: boolean;
17
+ selectEncoding: 'default' | 'none';
18
+ brushEncoding: 'x' | 'y' | 'default' | 'none';
19
+ hideLegend?: boolean;
20
+ }
21
+ export function getSingleView(props: SingleViewProps) {
22
+ const {
23
+ x,
24
+ y,
25
+ color,
26
+ opacity,
27
+ size,
28
+ shape,
29
+ theta,
30
+ radius,
31
+ row,
32
+ column,
33
+ xOffset,
34
+ yOffset,
35
+ defaultAggregated,
36
+ stack,
37
+ geomType,
38
+ selectEncoding,
39
+ brushEncoding,
40
+ enableCrossFilter,
41
+ asCrossFilterTrigger,
42
+ hideLegend = false,
43
+ } = props;
44
+ const fields: IViewField[] = [x, y, color, opacity, size, shape, row, column, xOffset, yOffset, theta, radius];
45
+ let markType = geomType;
46
+ let config: any = {};
47
+ if (hideLegend) {
48
+ config.legend = {
49
+ disable: true,
50
+ };
51
+ }
52
+ if (geomType === 'auto') {
53
+ const types: ISemanticType[] = [];
54
+ if (x !== NULL_FIELD) types.push(x.semanticType); //types.push(getFieldType(x));
55
+ if (y !== NULL_FIELD) types.push(y.semanticType); //types.push(getFieldType(yField));
56
+ markType = autoMark(types);
57
+ }
58
+
59
+ let encoding = channelEncode({
60
+ geomType: markType,
61
+ x,
62
+ y,
63
+ color,
64
+ opacity,
65
+ size,
66
+ shape,
67
+ row,
68
+ column,
69
+ xOffset,
70
+ yOffset,
71
+ theta,
72
+ radius,
73
+ });
74
+ if (defaultAggregated) {
75
+ channelAggregate(encoding, fields);
76
+ }
77
+ channelStack(encoding, stack);
78
+ if (!enableCrossFilter || (brushEncoding === 'none' && selectEncoding === 'none')) {
79
+ return {
80
+ config,
81
+ mark: {
82
+ type: markType,
83
+ opacity: 0.96,
84
+ tooltip: true,
85
+ },
86
+ encoding,
87
+ };
88
+ }
89
+ const mark = {
90
+ type: markType,
91
+ opacity: 0.96,
92
+ tooltip: true,
93
+ };
94
+
95
+ if (brushEncoding !== 'none') {
96
+ return {
97
+ config,
98
+ transform: asCrossFilterTrigger ? [] : [{ filter: { param: BRUSH_SIGNAL_NAME } }],
99
+ params: [
100
+ // {
101
+ // name: BRUSH_SIGNAL_DISPLAY_NAME,
102
+ // select: { type: 'interval', encodings: brushEncoding === 'default' ? undefined : [brushEncoding] },
103
+ // on: '__YOU_CANNOT_MODIFY_THIS_SIGNAL__',
104
+ // },
105
+ {
106
+ name: BRUSH_SIGNAL_NAME,
107
+ select: { type: 'interval', encodings: brushEncoding === 'default' ? undefined : [brushEncoding] },
108
+ },
109
+ ],
110
+ mark,
111
+ encoding,
112
+ };
113
+ }
114
+
115
+ return {
116
+ config,
117
+ transform: asCrossFilterTrigger ? [] : [{ filter: { param: POINT_SIGNAL_NAME } }],
118
+ params: [
119
+ {
120
+ name: POINT_SIGNAL_NAME,
121
+ select: { type: 'point' },
122
+ },
123
+ ],
124
+ mark,
125
+ encoding: asCrossFilterTrigger
126
+ ? {
127
+ ...encoding,
128
+ color: {
129
+ condition: {
130
+ ...encoding.color,
131
+ param: POINT_SIGNAL_NAME,
132
+ },
133
+ value: '#888',
134
+ },
135
+ }
136
+ : encoding,
137
+ };
138
+ }
package/src/vis/theme.ts CHANGED
@@ -56,6 +56,18 @@ export const AntVTheme = {
56
56
  ],
57
57
  diverging: ["#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
58
58
  heatmap: ["#000000", "#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
59
+ // ordinal: [
60
+ // '#B8E1FF',
61
+ // // '#9AC5FF',
62
+ // // '#7DAAFF',
63
+ // // '#5B8FF9',
64
+ // // '#3D76DD',
65
+ // // '#085EC0',
66
+ // // '#0047A5',
67
+ // // '#00318A',
68
+ // '#001D70'
69
+ // ],
70
+ // ordinal: 'blues',
59
71
  ramp: [
60
72
  "#EBCCFF",
61
73
  "#CCB0FF",
@@ -21,6 +21,7 @@ import {
21
21
  ChevronDoubleUpIcon,
22
22
  ArrowsUpDownIcon,
23
23
  LightBulbIcon,
24
+ CodeBracketSquareIcon,
24
25
  } from '@heroicons/react/24/outline';
25
26
  import { observer } from 'mobx-react-lite';
26
27
  import React, { SVGProps, useCallback, useMemo } from 'react';
@@ -66,7 +67,7 @@ interface IVisualSettings {
66
67
  }
67
68
 
68
69
  const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler, darkModePreference }) => {
69
- const { vizStore } = useGlobalStore();
70
+ const { vizStore, commonStore } = useGlobalStore();
70
71
  const { visualConfig, canUndo, canRedo } = vizStore;
71
72
  const { t: tGlobal } = useTranslation();
72
73
  const { t } = useTranslation('translation', { keyPrefix: 'main.tabpanel.settings' });
@@ -335,6 +336,14 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler, darkModePr
335
336
  </FormContainer>
336
337
  ),
337
338
  },
339
+ {
340
+ key: 'export_code',
341
+ label: t('button.export_code'),
342
+ icon: CodeBracketSquareIcon,
343
+ onClick: () => {
344
+ commonStore.setShowCodeExportPanel(true);
345
+ }
346
+ }
338
347
  ] as ToolbarItemProps[];
339
348
  }, [vizStore, canUndo, canRedo, defaultAggregated, markType, stack, interactiveScale, sizeMode, width, height, explorationMode, brushDirection, showActions, downloadPNG, downloadSVG, dark]);
340
349
 
@@ -0,0 +1,12 @@
1
+ import { IField, IRow } from "../interfaces";
2
+ import { dataframe2Dataset, dataset2DataFrame, execExpression } from "../lib/execExp";
3
+
4
+ export function transformData(data: IRow[], columns: IField[]) {
5
+ const computedFields = columns.filter((f) => f.computed);
6
+ let df = dataset2DataFrame(data, columns);
7
+ for (let i = 0; i < computedFields.length; i++) {
8
+ const field = computedFields[i];
9
+ df = execExpression(field.expressoion!, df, columns);
10
+ }
11
+ return dataframe2Dataset(df, columns);
12
+ }
@@ -0,0 +1,13 @@
1
+ import { transformData } from './transform'
2
+ const main = e => {
3
+ const { dataSource, columns } = e.data;
4
+
5
+ try {
6
+ const ans = transformData(dataSource, columns);
7
+ self.postMessage(ans);
8
+ } catch (error) {
9
+ self.postMessage({ error: error.message });
10
+ }
11
+ };
12
+
13
+ self.addEventListener('message', main, false);
@@ -0,0 +1,16 @@
1
+ import { queryView } from '../lib/viewQuery'
2
+ const main = e => {
3
+ try {
4
+ const { dataSource, metas, query } = e.data;
5
+ const ans = queryView(dataSource, metas, query);
6
+ self.postMessage(ans);
7
+
8
+ } catch (err) {
9
+ // console.log(err.s)
10
+ // log err stack
11
+ console.error(err.stack);
12
+ self.postMessage(err.stack);
13
+ }
14
+ };
15
+
16
+ self.addEventListener('message', main, false);
@@ -1,5 +0,0 @@
1
- import React from 'react';
2
- interface DSPanelProps {
3
- }
4
- declare const _default: React.FunctionComponent<DSPanelProps>;
5
- export default _default;
@@ -1,71 +0,0 @@
1
- import React, { useRef, useCallback } from 'react';
2
- import { FileReader } from '@kanaries/web-data-loader';
3
- import { IRow } from '../interfaces';
4
- import Table from './table';
5
- import styled from 'styled-components';
6
- import { useGlobalStore } from '../store';
7
- import { observer } from 'mobx-react-lite';
8
-
9
- const Container = styled.div`
10
- overflow-x: auto;
11
- `;
12
-
13
- interface DSPanelProps {
14
- }
15
- const DataSourcePanel: React.FC<DSPanelProps> = props => {
16
- const fileRef = useRef<HTMLInputElement>(null);
17
- const { commonStore } = useGlobalStore();
18
- const { tmpDSName, tmpDataSource } = commonStore;
19
-
20
- const onSubmitData = useCallback(() => {
21
- commonStore.commitTempDS();
22
- }, [])
23
- return (
24
- <Container>
25
- <input
26
- style={{ display: 'none' }}
27
- type="file"
28
- ref={fileRef}
29
- onChange={(e) => {
30
- const files = e.target.files;
31
- if (files !== null) {
32
- const file = files[0];
33
- FileReader.csvReader({
34
- file,
35
- config: { type: 'reservoirSampling', size: Infinity },
36
- onLoading: () => {}
37
- }).then((data) => {
38
- commonStore.updateTempDS(data as IRow[]);
39
- });
40
- }
41
- }}
42
- />
43
- <div className="mt-1 mb-1">
44
- <button className="inline-block min-w-96 text-xs mr-2 pt-1 pb-1 pl-6 pr-6 border border-gray-500 rounded-sm cursor-pointer hover:bg-gray-200"
45
- onClick={() => { if (fileRef.current) { fileRef.current.click(); }}}
46
- >
47
- 上传数据
48
- </button>
49
- <button className="inline-block min-w-96 text-xs mr-2 pt-1 pb-1 pl-6 pr-6 bg-yellow-600 rounded-sm hover:bg-yellow-500 text-white font-bold disabled:bg-gray-300"
50
- disabled={tmpDataSource.length === 0}
51
- onClick={() => { onSubmitData(); }}
52
- >
53
- 确认
54
- </button>
55
- </div>
56
- <div className="mt-1 mb-1">
57
- <label className="block text-xs text-gray-800">数据集名称</label>
58
- <input type="text" placeholder="数据集名称"
59
- value={tmpDSName}
60
- onChange={e => {
61
- commonStore.updateTempName(e.target.value)
62
- }}
63
- className="text-xs p-1 border border-gray-200 outline-none focus:outline-none focus:border-blue-500"
64
- />
65
- </div>
66
- <Table />
67
- </Container>
68
- );
69
- }
70
-
71
- export default observer(DataSourcePanel);