@kanaries/graphic-walker 0.2.13 → 0.2.15
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.
- package/dist/App.d.ts +6 -3
- package/dist/assets/explainer.worker-8428eb12.js.map +1 -1
- package/dist/components/button/base.d.ts +1 -0
- package/dist/components/button/defaultMini.d.ts +4 -0
- package/dist/components/button/primaryMini.d.ts +4 -0
- package/dist/components/callout.d.ts +2 -0
- package/dist/components/dropdownContext/index.d.ts +13 -0
- package/dist/components/dropdownSelect/index.d.ts +17 -0
- package/dist/components/modal.d.ts +1 -0
- package/dist/components/toolbar/components.d.ts +4 -1
- package/dist/components/toolbar/index.d.ts +2 -0
- package/dist/components/toolbar/toolbar-item.d.ts +4 -0
- package/dist/components/tooltip.d.ts +2 -0
- package/dist/dataSource/dataSelection/config.d.ts +2 -0
- package/dist/dataSource/index.d.ts +1 -1
- package/dist/fields/components.d.ts +0 -1
- package/dist/fields/datasetFields/dimFields.d.ts +2 -2
- package/dist/fields/datasetFields/meaFields.d.ts +2 -2
- package/dist/fields/encodeFields/singleEncodeDropDown.d.ts +17 -0
- package/dist/fields/encodeFields/singleEncodeEditor.d.ts +11 -0
- package/dist/fields/filterField/filterEditDialog.d.ts +1 -1
- package/dist/fields/obComponents/obPill.d.ts +3 -3
- package/dist/graphic-walker.es.js +21205 -19397
- package/dist/graphic-walker.es.js.map +1 -1
- package/dist/graphic-walker.umd.js +181 -236
- package/dist/graphic-walker.umd.js.map +1 -1
- package/dist/insightBoard/index.d.ts +1 -1
- package/dist/interfaces.d.ts +3 -0
- package/dist/renderer/index.d.ts +7 -3
- package/dist/store/visualSpecStore.d.ts +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/media.d.ts +3 -0
- package/dist/vis/react-vega.d.ts +5 -1
- package/dist/vis/theme.d.ts +146 -0
- package/dist/visualSettings/index.d.ts +2 -1
- package/package.json +2 -1
- package/src/App.tsx +24 -16
- package/src/components/button/base.ts +1 -0
- package/src/components/button/default.tsx +6 -2
- package/src/components/button/defaultMini.tsx +17 -0
- package/src/components/button/primary.tsx +6 -2
- package/src/components/button/primaryMini.tsx +21 -0
- package/src/components/callout.tsx +9 -4
- package/src/components/clickMenu.tsx +1 -5
- package/src/components/dataTable/index.tsx +42 -52
- package/src/components/dataTable/pagination.tsx +4 -4
- package/src/components/dataTypeIcon.tsx +1 -1
- package/src/components/dropdownContext/index.tsx +64 -0
- package/src/components/dropdownSelect/index.tsx +92 -0
- package/src/components/modal.tsx +20 -22
- package/src/components/sizeSetting.tsx +2 -2
- package/src/components/tabs/defaultTab.tsx +4 -4
- package/src/components/tabs/editableTab.tsx +5 -5
- package/src/components/toolbar/components.tsx +10 -8
- package/src/components/toolbar/index.tsx +16 -4
- package/src/components/toolbar/toolbar-button.tsx +8 -2
- package/src/components/toolbar/toolbar-item.tsx +18 -9
- package/src/components/toolbar/toolbar-select-button.tsx +21 -8
- package/src/components/toolbar/toolbar-toggle-button.tsx +8 -2
- package/src/components/tooltip.tsx +10 -3
- package/src/dataSource/dataSelection/config.ts +28 -0
- package/src/dataSource/dataSelection/csvData.tsx +77 -32
- package/src/dataSource/dataSelection/gwFile.tsx +0 -8
- package/src/dataSource/dataSelection/index.tsx +1 -2
- package/src/dataSource/dataSelection/publicData.tsx +2 -3
- package/src/dataSource/index.tsx +80 -61
- package/src/fields/aestheticFields.tsx +3 -1
- package/src/fields/components.tsx +20 -38
- package/src/fields/datasetFields/dimFields.tsx +43 -35
- package/src/fields/datasetFields/index.tsx +3 -4
- package/src/fields/datasetFields/meaFields.tsx +73 -47
- package/src/fields/encodeFields/singleEncodeDropDown.tsx +92 -0
- package/src/fields/encodeFields/singleEncodeEditor.tsx +78 -0
- package/src/fields/filterField/filterEditDialog.tsx +63 -98
- package/src/fields/filterField/filterPill.tsx +1 -1
- package/src/fields/filterField/slider.tsx +2 -2
- package/src/fields/filterField/tabs.tsx +11 -21
- package/src/fields/obComponents/obPill.tsx +65 -35
- package/src/index.css +13 -0
- package/src/insightBoard/index.tsx +24 -23
- package/src/insightBoard/mainBoard.tsx +9 -2
- package/src/insightBoard/radioGroupButtons.tsx +7 -0
- package/src/interfaces.ts +5 -1
- package/src/lib/inferMeta.ts +1 -1
- package/src/locales/en-US.json +11 -5
- package/src/locales/i18n.ts +7 -0
- package/src/locales/ja-JP.json +195 -0
- package/src/locales/zh-CN.json +9 -3
- package/src/main.tsx +1 -1
- package/src/renderer/index.tsx +96 -70
- package/src/store/visualSpecStore.ts +16 -0
- package/src/utils/index.ts +19 -0
- package/src/utils/media.ts +31 -0
- package/src/utils/normalization.ts +2 -1
- package/src/vis/react-vega.tsx +36 -5
- package/src/vis/theme.ts +124 -0
- package/src/visualSettings/index.tsx +29 -33
- package/dist/components/container.d.ts +0 -2
- package/src/components/container.tsx +0 -16
package/src/locales/en-US.json
CHANGED
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
},
|
|
51
51
|
"draggable_key": {
|
|
52
52
|
"fields": "Fields",
|
|
53
|
-
"columns": "
|
|
54
|
-
"rows": "
|
|
53
|
+
"columns": "X-Axis",
|
|
54
|
+
"rows": "Y-Axis",
|
|
55
55
|
"color": "Color",
|
|
56
56
|
"opacity": "Opacity",
|
|
57
57
|
"size": "Size",
|
|
@@ -105,7 +105,9 @@
|
|
|
105
105
|
"file": {
|
|
106
106
|
"open": "Open...",
|
|
107
107
|
"submit": "Submit",
|
|
108
|
-
"dataset_name": "Dataset Name"
|
|
108
|
+
"dataset_name": "Dataset Name",
|
|
109
|
+
"choose_file": "Choose a Data File",
|
|
110
|
+
"get_start_desc": "Get started by creating a dataset."
|
|
109
111
|
},
|
|
110
112
|
"public": {
|
|
111
113
|
"submit": "Submit"
|
|
@@ -165,7 +167,9 @@
|
|
|
165
167
|
"btn": {
|
|
166
168
|
"select_all": "Select All",
|
|
167
169
|
"unselect_all": "Unselect All",
|
|
168
|
-
"reverse": "Reverse Selection"
|
|
170
|
+
"reverse": "Reverse Selection",
|
|
171
|
+
"confirm": "Confirm",
|
|
172
|
+
"cancel": "Cancel"
|
|
169
173
|
}
|
|
170
174
|
},
|
|
171
175
|
"explain": {
|
|
@@ -184,6 +188,8 @@
|
|
|
184
188
|
},
|
|
185
189
|
"actions": {
|
|
186
190
|
"prev": "Previous",
|
|
187
|
-
"next": "Next"
|
|
191
|
+
"next": "Next",
|
|
192
|
+
"drop_field": "Drop Field Here",
|
|
193
|
+
"confirm": "Confirm"
|
|
188
194
|
}
|
|
189
195
|
}
|
package/src/locales/i18n.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { initReactI18next } from 'react-i18next';
|
|
|
3
3
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
4
4
|
|
|
5
5
|
import localeEnUs from './en-US.json';
|
|
6
|
+
import localeJaJp from './ja-JP.json';
|
|
6
7
|
import localeZhCn from './zh-CN.json';
|
|
7
8
|
|
|
8
9
|
|
|
@@ -19,6 +20,12 @@ const locales: Resource & { 'en-US': any } = {
|
|
|
19
20
|
'zh-CN': {
|
|
20
21
|
translation: localeZhCn,
|
|
21
22
|
},
|
|
23
|
+
'ja': {
|
|
24
|
+
translation: localeJaJp,
|
|
25
|
+
},
|
|
26
|
+
'ja-JP': {
|
|
27
|
+
translation: localeJaJp,
|
|
28
|
+
}
|
|
22
29
|
} as const;
|
|
23
30
|
|
|
24
31
|
i18n.use(initReactI18next).use(LanguageDetector).init({
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
{
|
|
2
|
+
"constant": {
|
|
3
|
+
"row_count": "行数",
|
|
4
|
+
"analytic_type": {
|
|
5
|
+
"dimension": "次元",
|
|
6
|
+
"measure": "尺度"
|
|
7
|
+
},
|
|
8
|
+
"semantic_type": {
|
|
9
|
+
"nominal": "名義尺度",
|
|
10
|
+
"ordinal": "順序尺度",
|
|
11
|
+
"temporal": "時間尺度",
|
|
12
|
+
"quantitative": "数量尺度"
|
|
13
|
+
},
|
|
14
|
+
"mark_type": {
|
|
15
|
+
"__enum__": "マークタイプ",
|
|
16
|
+
"auto": "自動",
|
|
17
|
+
"bar": "バー",
|
|
18
|
+
"line": "ライン",
|
|
19
|
+
"area": "エリア",
|
|
20
|
+
"trail": "トレイル",
|
|
21
|
+
"point": "散布図",
|
|
22
|
+
"circle": "円",
|
|
23
|
+
"tick": "棒線図",
|
|
24
|
+
"rect": "長方形",
|
|
25
|
+
"arc": "アーク",
|
|
26
|
+
"boxplot": "ボックスプロット"
|
|
27
|
+
},
|
|
28
|
+
"stack_mode": {
|
|
29
|
+
"__enum__": "スタックモード",
|
|
30
|
+
"none": "なし",
|
|
31
|
+
"stack": "スタック",
|
|
32
|
+
"normalize": "正規化"
|
|
33
|
+
},
|
|
34
|
+
"layout_type": {
|
|
35
|
+
"__enum__": "レイアウトタイプ",
|
|
36
|
+
"auto": "自動",
|
|
37
|
+
"fixed": "固定"
|
|
38
|
+
},
|
|
39
|
+
"exploration_mode": {
|
|
40
|
+
"__enum__": "探索モード",
|
|
41
|
+
"none": "オフ",
|
|
42
|
+
"brush": "ブラシ",
|
|
43
|
+
"point": "ポイント"
|
|
44
|
+
},
|
|
45
|
+
"brush_mode": {
|
|
46
|
+
"__enum__": "ブラシの方向",
|
|
47
|
+
"default": "両方",
|
|
48
|
+
"x": "X軸のみ",
|
|
49
|
+
"y": "Y軸のみ"
|
|
50
|
+
},
|
|
51
|
+
"draggable_key": {
|
|
52
|
+
"fields": "フィールド",
|
|
53
|
+
"columns": "X軸",
|
|
54
|
+
"rows": "Y軸",
|
|
55
|
+
"color": "色",
|
|
56
|
+
"opacity": "不透明度",
|
|
57
|
+
"size": "大きさ",
|
|
58
|
+
"shape": "形状",
|
|
59
|
+
"theta": "角度",
|
|
60
|
+
"radius": "半径",
|
|
61
|
+
"filters": "フィルター"
|
|
62
|
+
},
|
|
63
|
+
"aggregator": {
|
|
64
|
+
"sum": "合計",
|
|
65
|
+
"mean": "平均",
|
|
66
|
+
"count": "件数",
|
|
67
|
+
"median": "中央値",
|
|
68
|
+
"min": "最小値",
|
|
69
|
+
"max": "最大値",
|
|
70
|
+
"q1": "第一四分位数",
|
|
71
|
+
"q3": "第三四分位数",
|
|
72
|
+
"stdev": "標準偏差",
|
|
73
|
+
"variance": "分散"
|
|
74
|
+
},
|
|
75
|
+
"filter_type": {
|
|
76
|
+
"one_of": "1つ以上",
|
|
77
|
+
"range": "範囲",
|
|
78
|
+
"temporal_range": "日付範囲"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"App": {
|
|
82
|
+
"labels": {
|
|
83
|
+
"data_interpretation": "データ解釈"
|
|
84
|
+
},
|
|
85
|
+
"segments": {
|
|
86
|
+
"vis": "可視化",
|
|
87
|
+
"data": "データ"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"DataSource": {
|
|
91
|
+
"labels": {
|
|
92
|
+
"cur_dataset": "現在のデータセット"
|
|
93
|
+
},
|
|
94
|
+
"buttons": {
|
|
95
|
+
"create_dataset": "データセットを作成",
|
|
96
|
+
"export_as_file": "ファイルとして保存",
|
|
97
|
+
"import_file": "Graphic Walkerファイルをインポート"
|
|
98
|
+
},
|
|
99
|
+
"dialog": {
|
|
100
|
+
"create_data_source": "新しいデータソース",
|
|
101
|
+
"data_types": "データソースの種類",
|
|
102
|
+
"text_file_data": "ローカルファイル",
|
|
103
|
+
"public_data": "公開データセット",
|
|
104
|
+
"data_source_type": "データソースの種類:{{sourceType}}",
|
|
105
|
+
"file": {
|
|
106
|
+
"open": "開く...",
|
|
107
|
+
"submit": "提出する",
|
|
108
|
+
"dataset_name": "データセット名",
|
|
109
|
+
"choose_file": "データファイルを選択してください",
|
|
110
|
+
"get_start_desc": "データセットの作成を始めましょう。"
|
|
111
|
+
},
|
|
112
|
+
"public": {
|
|
113
|
+
"submit": "提出する"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"main": {
|
|
118
|
+
"tablist": {
|
|
119
|
+
"new": "+ 新規作成",
|
|
120
|
+
"autoTitle": "グラフ {{idx}}"
|
|
121
|
+
},
|
|
122
|
+
"tabpanel": {
|
|
123
|
+
"menubar": {
|
|
124
|
+
"undo": "元に戻す",
|
|
125
|
+
"redo": "やり直し"
|
|
126
|
+
},
|
|
127
|
+
"settings": {
|
|
128
|
+
"toggle": {
|
|
129
|
+
"aggregation": "集計",
|
|
130
|
+
"stack": "スタック",
|
|
131
|
+
"axes_resize": "軸のサイズ変更",
|
|
132
|
+
"debug": "デバッグ"
|
|
133
|
+
},
|
|
134
|
+
"sort": "並べ替えの順序",
|
|
135
|
+
"button": {
|
|
136
|
+
"ascending": "昇順に並べ替える",
|
|
137
|
+
"descending": "降順に並べ替える",
|
|
138
|
+
"transpose": "転置",
|
|
139
|
+
"export_chart": "エクスポート",
|
|
140
|
+
"export_chart_as": "{{type}}としてエクスポート"
|
|
141
|
+
},
|
|
142
|
+
"size": "サイズ変更",
|
|
143
|
+
"size_setting": {
|
|
144
|
+
"width": "幅",
|
|
145
|
+
"height": "高さ"
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
"DatasetFields": {
|
|
149
|
+
"field_list": "フィールド一覧"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
"filters": {
|
|
154
|
+
"to_edit": "このルールを編集",
|
|
155
|
+
"empty_rule": "! (空のルール)",
|
|
156
|
+
"editing": "ルールを編集",
|
|
157
|
+
"form": {
|
|
158
|
+
"name": "フィールド",
|
|
159
|
+
"rule": "ルール"
|
|
160
|
+
},
|
|
161
|
+
"header": {
|
|
162
|
+
"visibility": "表示",
|
|
163
|
+
"value": "ラベル",
|
|
164
|
+
"count": "件数"
|
|
165
|
+
},
|
|
166
|
+
"selected_keys": "{{ count }}件が選択されました",
|
|
167
|
+
"btn": {
|
|
168
|
+
"select_all": "すべて選択",
|
|
169
|
+
"unselect_all": "すべての選択を解除",
|
|
170
|
+
"reverse": "選択を反転する",
|
|
171
|
+
"confirm": "確認",
|
|
172
|
+
"cancel": "キャンセル"
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
"explain": {
|
|
176
|
+
"lg_than": "より大きい",
|
|
177
|
+
"sm_than": "より小さい",
|
|
178
|
+
"expection": "期待値",
|
|
179
|
+
"unrecognized": "未認識",
|
|
180
|
+
"score": "スコア",
|
|
181
|
+
"contains": "を含む",
|
|
182
|
+
"reason": {
|
|
183
|
+
"selection_dim_distribution": "次元のヒント",
|
|
184
|
+
"selection_mea_distribution": "尺度のヒント",
|
|
185
|
+
"children_major_factor": "主要要因",
|
|
186
|
+
"children_outlier": "外れ値"
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"actions": {
|
|
190
|
+
"prev": "前へ",
|
|
191
|
+
"next": "次へ",
|
|
192
|
+
"drop_field": "ここにフィールドをドロップ",
|
|
193
|
+
"confirm": "確認"
|
|
194
|
+
}
|
|
195
|
+
}
|
package/src/locales/zh-CN.json
CHANGED
|
@@ -105,7 +105,9 @@
|
|
|
105
105
|
"file": {
|
|
106
106
|
"open": "打开文件...",
|
|
107
107
|
"submit": "确认",
|
|
108
|
-
"dataset_name": "数据集名称"
|
|
108
|
+
"dataset_name": "数据集名称",
|
|
109
|
+
"choose_file": "选择文件",
|
|
110
|
+
"get_start_desc": "创建一个数据集以开始分析"
|
|
109
111
|
},
|
|
110
112
|
"public": {
|
|
111
113
|
"submit": "确认"
|
|
@@ -165,7 +167,9 @@
|
|
|
165
167
|
"btn": {
|
|
166
168
|
"select_all": "全部选中",
|
|
167
169
|
"unselect_all": "全部取消",
|
|
168
|
-
"reverse": "选择反向"
|
|
170
|
+
"reverse": "选择反向",
|
|
171
|
+
"confirm": "确认",
|
|
172
|
+
"cancel": "取消"
|
|
169
173
|
}
|
|
170
174
|
},
|
|
171
175
|
"explain": {
|
|
@@ -184,6 +188,8 @@
|
|
|
184
188
|
},
|
|
185
189
|
"actions": {
|
|
186
190
|
"prev": "向前",
|
|
187
|
-
"next": "向后"
|
|
191
|
+
"next": "向后",
|
|
192
|
+
"drop_field": "拖拽字段至此",
|
|
193
|
+
"confirm": "确认"
|
|
188
194
|
}
|
|
189
195
|
}
|
package/src/main.tsx
CHANGED
package/src/renderer/index.tsx
CHANGED
|
@@ -1,44 +1,50 @@
|
|
|
1
|
-
import { runInAction, toJS } from
|
|
2
|
-
import { observer } from
|
|
3
|
-
import { Resizable } from
|
|
4
|
-
import React, { useState, useCallback, useEffect, useRef, forwardRef } from
|
|
5
|
-
import { applyFilter } from
|
|
6
|
-
import { useGlobalStore } from
|
|
7
|
-
import ReactVega, { IReactVegaHandler } from
|
|
1
|
+
import { runInAction, toJS } from "mobx";
|
|
2
|
+
import { observer } from "mobx-react-lite";
|
|
3
|
+
import { Resizable } from "re-resizable";
|
|
4
|
+
import React, { useState, useCallback, useEffect, useRef, forwardRef } from "react";
|
|
5
|
+
import { applyFilter } from "../services";
|
|
6
|
+
import { useGlobalStore } from "../store";
|
|
7
|
+
import ReactVega, { IReactVegaHandler } from "../vis/react-vega";
|
|
8
|
+
import { IDarkMode, IThemeKey } from "../interfaces";
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
const ReactiveRenderer = forwardRef<IReactVegaHandler, { themeKey?: IThemeKey; dark?: IDarkMode }>(function ReactiveRenderer(
|
|
11
|
+
{ themeKey, dark },
|
|
12
|
+
ref
|
|
13
|
+
) {
|
|
11
14
|
const { vizStore, commonStore } = useGlobalStore();
|
|
12
15
|
const { draggableFieldState, visualConfig } = vizStore;
|
|
13
16
|
const { geoms, interactiveScale, defaultAggregated, stack, showActions, size, exploration } = visualConfig;
|
|
14
17
|
const { currentDataset } = commonStore;
|
|
15
18
|
const { filters } = draggableFieldState;
|
|
16
19
|
|
|
17
|
-
const rows = toJS(draggableFieldState.rows)
|
|
18
|
-
const columns = toJS(draggableFieldState.columns)
|
|
19
|
-
const color = toJS(draggableFieldState.color)
|
|
20
|
-
const opacity = toJS(draggableFieldState.opacity)
|
|
21
|
-
const shape = toJS(draggableFieldState.shape)
|
|
22
|
-
const theta = toJS(draggableFieldState.theta)
|
|
23
|
-
const radius = toJS(draggableFieldState.radius)
|
|
24
|
-
const sizeChannel = toJS(draggableFieldState.size)
|
|
20
|
+
const rows = toJS(draggableFieldState.rows);
|
|
21
|
+
const columns = toJS(draggableFieldState.columns);
|
|
22
|
+
const color = toJS(draggableFieldState.color);
|
|
23
|
+
const opacity = toJS(draggableFieldState.opacity);
|
|
24
|
+
const shape = toJS(draggableFieldState.shape);
|
|
25
|
+
const theta = toJS(draggableFieldState.theta);
|
|
26
|
+
const radius = toJS(draggableFieldState.radius);
|
|
27
|
+
const sizeChannel = toJS(draggableFieldState.size);
|
|
25
28
|
|
|
26
|
-
const rowLeftFacetFields = rows.slice(0, -1).filter(f => f.analyticType ===
|
|
27
|
-
const colLeftFacetFields = columns.slice(0, -1).filter(f => f.analyticType ===
|
|
29
|
+
const rowLeftFacetFields = rows.slice(0, -1).filter((f) => f.analyticType === "dimension");
|
|
30
|
+
const colLeftFacetFields = columns.slice(0, -1).filter((f) => f.analyticType === "dimension");
|
|
28
31
|
|
|
29
32
|
const hasFacet = rowLeftFacetFields.length > 0 || colLeftFacetFields.length > 0;
|
|
30
33
|
|
|
31
|
-
const shouldTriggerMenu = exploration.mode ===
|
|
32
|
-
|
|
33
|
-
const handleGeomClick = useCallback(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
const shouldTriggerMenu = exploration.mode === "none";
|
|
35
|
+
|
|
36
|
+
const handleGeomClick = useCallback(
|
|
37
|
+
(values: any, e: any) => {
|
|
38
|
+
if (shouldTriggerMenu) {
|
|
39
|
+
e.stopPropagation();
|
|
40
|
+
runInAction(() => {
|
|
41
|
+
commonStore.showEmbededMenu([e.pageX, e.pageY]);
|
|
42
|
+
commonStore.setFilters(values);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
[shouldTriggerMenu]
|
|
47
|
+
);
|
|
42
48
|
|
|
43
49
|
// apply filters
|
|
44
50
|
const { dataSource } = currentDataset;
|
|
@@ -54,14 +60,14 @@ const ReactiveRenderer = forwardRef<IReactVegaHandler, {}>(function ReactiveRend
|
|
|
54
60
|
const p = filters.length === 0 ? Promise.resolve(dataSource) : applyFilter(dataSource, filters);
|
|
55
61
|
pendingPromiseRef.current = p;
|
|
56
62
|
|
|
57
|
-
p.then(d => {
|
|
63
|
+
p.then((d) => {
|
|
58
64
|
if (p !== pendingPromiseRef.current) {
|
|
59
65
|
// This promise is out-of-date
|
|
60
66
|
return;
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
setData(d);
|
|
64
|
-
}).catch(err => {
|
|
70
|
+
}).catch((err) => {
|
|
65
71
|
console.error(err);
|
|
66
72
|
});
|
|
67
73
|
|
|
@@ -69,44 +75,64 @@ const ReactiveRenderer = forwardRef<IReactVegaHandler, {}>(function ReactiveRend
|
|
|
69
75
|
pendingPromiseRef.current = null;
|
|
70
76
|
};
|
|
71
77
|
}, [dataSource, filters]);
|
|
72
|
-
|
|
73
|
-
return
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
78
|
+
const enableResize = size.mode === "fixed" && !hasFacet;
|
|
79
|
+
return (
|
|
80
|
+
<Resizable
|
|
81
|
+
className={enableResize ? "border-blue-400 border-2 overflow-hidden" : ""}
|
|
82
|
+
style={{ padding: "12px" }}
|
|
83
|
+
onResizeStop={(e, direction, ref, d) => {
|
|
84
|
+
vizStore.setChartLayout({
|
|
85
|
+
mode: "fixed",
|
|
86
|
+
width: size.width + d.width,
|
|
87
|
+
height: size.height + d.height,
|
|
88
|
+
});
|
|
89
|
+
}}
|
|
90
|
+
enable={
|
|
91
|
+
enableResize
|
|
92
|
+
? undefined
|
|
93
|
+
: {
|
|
94
|
+
top: false,
|
|
95
|
+
right: false,
|
|
96
|
+
bottom: false,
|
|
97
|
+
left: false,
|
|
98
|
+
topRight: false,
|
|
99
|
+
bottomRight: false,
|
|
100
|
+
bottomLeft: false,
|
|
101
|
+
topLeft: false,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
size={{
|
|
105
|
+
width: size.width + "px",
|
|
106
|
+
height: size.height + "px",
|
|
107
|
+
}}
|
|
108
|
+
>
|
|
109
|
+
<ReactVega
|
|
110
|
+
layoutMode={size.mode}
|
|
111
|
+
interactiveScale={interactiveScale}
|
|
112
|
+
geomType={geoms[0]}
|
|
113
|
+
defaultAggregate={defaultAggregated}
|
|
114
|
+
stack={stack}
|
|
115
|
+
dataSource={data}
|
|
116
|
+
rows={rows}
|
|
117
|
+
columns={columns}
|
|
118
|
+
color={color[0]}
|
|
119
|
+
theta={theta[0]}
|
|
120
|
+
radius={radius[0]}
|
|
121
|
+
shape={shape[0]}
|
|
122
|
+
opacity={opacity[0]}
|
|
123
|
+
size={sizeChannel[0]}
|
|
124
|
+
showActions={showActions}
|
|
125
|
+
width={size.width - 12 * 4}
|
|
126
|
+
height={size.height - 12 * 4}
|
|
127
|
+
ref={ref}
|
|
128
|
+
brushEncoding={exploration.mode === "brush" ? exploration.brushDirection : "none"}
|
|
129
|
+
selectEncoding={exploration.mode === "point" ? "default" : "none"}
|
|
130
|
+
onGeomClick={handleGeomClick}
|
|
131
|
+
themeKey={themeKey}
|
|
132
|
+
dark={dark}
|
|
133
|
+
/>
|
|
134
|
+
</Resizable>
|
|
135
|
+
);
|
|
110
136
|
});
|
|
111
137
|
|
|
112
138
|
export default observer(ReactiveRenderer);
|
|
@@ -53,6 +53,7 @@ function initEncoding(): DraggableFieldState {
|
|
|
53
53
|
shape: [],
|
|
54
54
|
radius: [],
|
|
55
55
|
theta: [],
|
|
56
|
+
details: [],
|
|
56
57
|
filters: [],
|
|
57
58
|
};
|
|
58
59
|
}
|
|
@@ -444,6 +445,21 @@ export class VizSpecStore {
|
|
|
444
445
|
fields.splice(sourceIndex, 1);
|
|
445
446
|
});
|
|
446
447
|
}
|
|
448
|
+
public replaceField(sourceKey: keyof DraggableFieldState, sourceIndex: number, fid: string) {
|
|
449
|
+
if (MetaFieldKeys.includes(sourceKey)) return;
|
|
450
|
+
const enteringField = [
|
|
451
|
+
...this.draggableFieldState.dimensions,
|
|
452
|
+
...this.draggableFieldState.measures
|
|
453
|
+
].find(which => which.fid === fid);
|
|
454
|
+
if (!enteringField) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
this.useMutable(({ encodings }) => {
|
|
459
|
+
const fields = encodings[sourceKey];
|
|
460
|
+
fields.splice(sourceIndex, 1, toJS(enteringField));
|
|
461
|
+
});
|
|
462
|
+
}
|
|
447
463
|
private appendFilter(index: number, data: IViewField) {
|
|
448
464
|
this.useMutable(({ encodings }) => {
|
|
449
465
|
encodings.filters.splice(index, 0, {
|
package/src/utils/index.ts
CHANGED
|
@@ -258,3 +258,22 @@ export function extendCountField(
|
|
|
258
258
|
fields: nextFields,
|
|
259
259
|
};
|
|
260
260
|
}
|
|
261
|
+
|
|
262
|
+
export function getRange (nums: number[]): [number, number] {
|
|
263
|
+
let _min = Infinity;
|
|
264
|
+
let _max = -Infinity;
|
|
265
|
+
for (let i = 0; i < nums.length; i++) {
|
|
266
|
+
_min = Math.min(_min, nums[i]);
|
|
267
|
+
_max = Math.max(_max, nums[i]);
|
|
268
|
+
}
|
|
269
|
+
return [_min, _max];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function makeNumbersBeautiful (nums: number[]): number[] {
|
|
273
|
+
const [min, max] = getRange(nums);
|
|
274
|
+
const range = max - min;
|
|
275
|
+
const step = Math.pow(10, Math.floor(Math.log10(range)));
|
|
276
|
+
return nums.map((num) => {
|
|
277
|
+
return Math.round(num / step) * step;
|
|
278
|
+
})
|
|
279
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { IDarkMode } from "../interfaces";
|
|
3
|
+
|
|
4
|
+
export function currentMediaTheme(): "dark" | "light" {
|
|
5
|
+
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
6
|
+
return "dark";
|
|
7
|
+
} else {
|
|
8
|
+
return "light";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function useCurrentMediaTheme(mode: IDarkMode | undefined = 'media'): "dark" | "light" {
|
|
13
|
+
const [theme, setTheme] = useState<"dark" | "light">(mode === 'media' ? currentMediaTheme() : mode);
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (mode === 'media') {
|
|
17
|
+
const mediaQuery = window.matchMedia?.("(prefers-color-scheme: dark)") as MediaQueryList | undefined;
|
|
18
|
+
const listener = (e: MediaQueryListEvent) => {
|
|
19
|
+
setTheme(e.matches ? "dark" : "light");
|
|
20
|
+
};
|
|
21
|
+
mediaQuery?.addEventListener("change", listener);
|
|
22
|
+
return () => {
|
|
23
|
+
mediaQuery?.removeEventListener("change", listener);
|
|
24
|
+
};
|
|
25
|
+
} else {
|
|
26
|
+
setTheme(mode);
|
|
27
|
+
}
|
|
28
|
+
}, [mode]);
|
|
29
|
+
|
|
30
|
+
return theme;
|
|
31
|
+
}
|
|
@@ -140,12 +140,13 @@ export function makeBinField(dataSource: IRow[], fid: string, binFid: string, bi
|
|
|
140
140
|
if (val < _min) _min = val;
|
|
141
141
|
}
|
|
142
142
|
const step = (_max - _min) / binSize;
|
|
143
|
+
const beaStep = Math.max(-Math.round(Math.log10(_max - _min)) + 2, 0)
|
|
143
144
|
return dataSource.map((r) => {
|
|
144
145
|
let bIndex = Math.floor((r[fid] - _min) / step);
|
|
145
146
|
if (bIndex === binSize) bIndex = binSize - 1;
|
|
146
147
|
return {
|
|
147
148
|
...r,
|
|
148
|
-
[binFid]: bIndex * step + _min,
|
|
149
|
+
[binFid]: Number(((bIndex * step + _min)).toFixed(beaStep)),
|
|
149
150
|
};
|
|
150
151
|
});
|
|
151
152
|
}
|