@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/vis/react-vega.tsx
CHANGED
|
@@ -8,9 +8,11 @@ import styled from 'styled-components';
|
|
|
8
8
|
import { autoMark } from '../utils/autoMark';
|
|
9
9
|
import { COUNT_FIELD_ID } from '../constants';
|
|
10
10
|
|
|
11
|
-
import { IViewField, IRow, IStackMode } from '../interfaces';
|
|
11
|
+
import { IViewField, IRow, IStackMode, IDarkMode, IThemeKey } from '../interfaces';
|
|
12
12
|
import { useTranslation } from 'react-i18next';
|
|
13
13
|
import { getVegaTimeFormatRules } from './temporalFormat';
|
|
14
|
+
import { builtInThemes } from './theme';
|
|
15
|
+
import { useCurrentMediaTheme } from '../utils/media';
|
|
14
16
|
|
|
15
17
|
const CanvaContainer = styled.div<{rowSize: number; colSize: number;}>`
|
|
16
18
|
display: grid;
|
|
@@ -46,6 +48,9 @@ interface ReactVegaProps {
|
|
|
46
48
|
onGeomClick?: (values: any, e: any) => void
|
|
47
49
|
selectEncoding: SingleViewProps['selectEncoding'];
|
|
48
50
|
brushEncoding: SingleViewProps['brushEncoding'];
|
|
51
|
+
/** @default "vega" */
|
|
52
|
+
themeKey?: IThemeKey;
|
|
53
|
+
dark?: IDarkMode;
|
|
49
54
|
}
|
|
50
55
|
const NULL_FIELD: IViewField = {
|
|
51
56
|
dragId: '',
|
|
@@ -100,6 +105,7 @@ interface SingleViewProps {
|
|
|
100
105
|
asCrossFilterTrigger: boolean;
|
|
101
106
|
selectEncoding: 'default' | 'none';
|
|
102
107
|
brushEncoding: 'x' | 'y' | 'default' | 'none';
|
|
108
|
+
hideLegend?: boolean;
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
function availableChannels (geomType: string): Set<string> {
|
|
@@ -119,7 +125,15 @@ function channelEncode(props: EncodeProps) {
|
|
|
119
125
|
encoding[c] = {
|
|
120
126
|
field: props[c].fid,
|
|
121
127
|
title: props[c].name,
|
|
122
|
-
type: props[c].semanticType
|
|
128
|
+
type: props[c].semanticType,
|
|
129
|
+
}
|
|
130
|
+
if (props[c].analyticType !== 'measure') {
|
|
131
|
+
// if `aggregate` is set to null,
|
|
132
|
+
// do not aggregate this field
|
|
133
|
+
encoding[c].aggregate = null;
|
|
134
|
+
}
|
|
135
|
+
if (props[c].analyticType === 'measure') {
|
|
136
|
+
encoding[c].type = 'quantitative'
|
|
123
137
|
}
|
|
124
138
|
}
|
|
125
139
|
})
|
|
@@ -143,7 +157,7 @@ function channelEncode(props: EncodeProps) {
|
|
|
143
157
|
}
|
|
144
158
|
function channelAggregate(encoding: {[key: string]: any}, fields: IViewField[]) {
|
|
145
159
|
Object.values(encoding).forEach(c => {
|
|
146
|
-
const targetField = fields.find(f => f.fid === c.field);
|
|
160
|
+
const targetField = fields.find(f => f.fid === c.field && !('aggregate' in c));
|
|
147
161
|
if (targetField && targetField.fid === COUNT_FIELD_ID) {
|
|
148
162
|
c.field = undefined;
|
|
149
163
|
c.aggregate = 'count';
|
|
@@ -190,9 +204,16 @@ function getSingleView(props: SingleViewProps) {
|
|
|
190
204
|
brushEncoding,
|
|
191
205
|
enableCrossFilter,
|
|
192
206
|
asCrossFilterTrigger,
|
|
207
|
+
hideLegend = false,
|
|
193
208
|
} = props
|
|
194
209
|
const fields: IViewField[] = [x, y, color, opacity, size, shape, row, column, xOffset, yOffset, theta, radius]
|
|
195
210
|
let markType = geomType;
|
|
211
|
+
let config: any = {};
|
|
212
|
+
if (hideLegend) {
|
|
213
|
+
config.legend = {
|
|
214
|
+
disable: true
|
|
215
|
+
};
|
|
216
|
+
}
|
|
196
217
|
if (geomType === 'auto') {
|
|
197
218
|
const types: ISemanticType[] = [];
|
|
198
219
|
if (x !== NULL_FIELD) types.push(x.semanticType)//types.push(getFieldType(x));
|
|
@@ -207,6 +228,7 @@ function getSingleView(props: SingleViewProps) {
|
|
|
207
228
|
channelStack(encoding, stack);
|
|
208
229
|
if (!enableCrossFilter || brushEncoding === 'none' && selectEncoding === 'none') {
|
|
209
230
|
return {
|
|
231
|
+
config,
|
|
210
232
|
mark: {
|
|
211
233
|
type: markType,
|
|
212
234
|
opacity: 0.96,
|
|
@@ -314,6 +336,7 @@ function getSingleView(props: SingleViewProps) {
|
|
|
314
336
|
|
|
315
337
|
if (brushEncoding !== 'none') {
|
|
316
338
|
return {
|
|
339
|
+
config,
|
|
317
340
|
transform: asCrossFilterTrigger ? [] : [
|
|
318
341
|
{ filter: { param: BRUSH_SIGNAL_NAME } }
|
|
319
342
|
],
|
|
@@ -334,6 +357,7 @@ function getSingleView(props: SingleViewProps) {
|
|
|
334
357
|
}
|
|
335
358
|
|
|
336
359
|
return {
|
|
360
|
+
config,
|
|
337
361
|
transform: asCrossFilterTrigger ? [] : [
|
|
338
362
|
{ filter: { param: POINT_SIGNAL_NAME } }
|
|
339
363
|
],
|
|
@@ -378,11 +402,15 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
378
402
|
height,
|
|
379
403
|
selectEncoding,
|
|
380
404
|
brushEncoding,
|
|
405
|
+
themeKey = 'vega',
|
|
406
|
+
dark = 'media'
|
|
381
407
|
} = props;
|
|
382
408
|
// const container = useRef<HTMLDivElement>(null);
|
|
383
409
|
// const containers = useRef<(HTMLDivElement | null)[]>([]);
|
|
384
410
|
const [viewPlaceholders, setViewPlaceholders] = useState<React.MutableRefObject<HTMLDivElement>[]>([]);
|
|
385
411
|
const { i18n } = useTranslation();
|
|
412
|
+
const mediaTheme = useCurrentMediaTheme(dark);
|
|
413
|
+
const themeConfig = builtInThemes[themeKey]?.[mediaTheme];
|
|
386
414
|
useEffect(() => {
|
|
387
415
|
const clickSub = geomClick$.subscribe(([values, e]) => {
|
|
388
416
|
if (onGeomClick) {
|
|
@@ -502,7 +530,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
502
530
|
spec.params.push(...singleView.params!);
|
|
503
531
|
}
|
|
504
532
|
if (viewPlaceholders.length > 0 && viewPlaceholders[0].current) {
|
|
505
|
-
embed(viewPlaceholders[0].current, spec, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language) }).then(res => {
|
|
533
|
+
embed(viewPlaceholders[0].current, spec, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config: themeConfig }).then(res => {
|
|
506
534
|
vegaRefs.current = [res.view];
|
|
507
535
|
try {
|
|
508
536
|
res.view.addEventListener('click', (e) => {
|
|
@@ -538,6 +566,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
538
566
|
for (let i = 0; i < rowRepeatFields.length; i++) {
|
|
539
567
|
for (let j = 0; j < colRepeatFields.length; j++, index++) {
|
|
540
568
|
const sourceId = index;
|
|
569
|
+
const hasLegend = i === 0 && j === colRepeatFields.length - 1;
|
|
541
570
|
const singleView = getSingleView({
|
|
542
571
|
x: colRepeatFields[j] || NULL_FIELD,
|
|
543
572
|
y: rowRepeatFields[i] || NULL_FIELD,
|
|
@@ -558,6 +587,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
558
587
|
brushEncoding,
|
|
559
588
|
enableCrossFilter: crossFilterTriggerIdx !== -1,
|
|
560
589
|
asCrossFilterTrigger: crossFilterTriggerIdx === sourceId,
|
|
590
|
+
hideLegend: !hasLegend,
|
|
561
591
|
});
|
|
562
592
|
const node = i * colRepeatFields.length + j < viewPlaceholders.length ? viewPlaceholders[i * colRepeatFields.length + j].current : null
|
|
563
593
|
let commonSpec = { ...spec };
|
|
@@ -583,7 +613,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
583
613
|
ans.params = commonSpec.params;
|
|
584
614
|
}
|
|
585
615
|
if (node) {
|
|
586
|
-
embed(node, ans, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language) }).then(res => {
|
|
616
|
+
embed(node, ans, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config: themeConfig }).then(res => {
|
|
587
617
|
vegaRefs.current.push(res.view);
|
|
588
618
|
const paramStores = (res.vgSpec.data?.map(d => d.name) ?? []).filter(
|
|
589
619
|
name => [BRUSH_SIGNAL_NAME, POINT_SIGNAL_NAME].map(p => `${p}_store`).includes(name)
|
|
@@ -673,6 +703,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
|
|
|
673
703
|
selectEncoding,
|
|
674
704
|
brushEncoding,
|
|
675
705
|
crossFilterTriggerIdx,
|
|
706
|
+
themeConfig,
|
|
676
707
|
]);
|
|
677
708
|
|
|
678
709
|
useImperativeHandle(ref, () => ({
|
package/src/vis/theme.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const DEFAULT_COLOR = "#5B8FF9";
|
|
2
|
+
const DARK_COMMON_DESIGN = {
|
|
3
|
+
background: "transparent",
|
|
4
|
+
header: {
|
|
5
|
+
titleColor: "#d1d5db", // change title color to white
|
|
6
|
+
labelColor: "#d1d5db", // change label color to white
|
|
7
|
+
},
|
|
8
|
+
axis: {
|
|
9
|
+
gridColor: "#666",
|
|
10
|
+
domainColor: "#d1d5db", // change axis color to white
|
|
11
|
+
tickColor: "#d1d5db", // change tick color to white
|
|
12
|
+
labelColor: "#d1d5db", // change label color to white
|
|
13
|
+
titleColor: "#d1d5db", // change title color to white
|
|
14
|
+
},
|
|
15
|
+
legend: {
|
|
16
|
+
labelColor: "#d1d5db", // change legend label color to white
|
|
17
|
+
titleColor: "#d1d5db" // change legend title color to white
|
|
18
|
+
},
|
|
19
|
+
view: {
|
|
20
|
+
stroke: '#666'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export const VegaTheme = {
|
|
24
|
+
light: {
|
|
25
|
+
background: "transparent",
|
|
26
|
+
},
|
|
27
|
+
dark: DARK_COMMON_DESIGN
|
|
28
|
+
} as const;
|
|
29
|
+
|
|
30
|
+
export const AntVTheme = {
|
|
31
|
+
light: {
|
|
32
|
+
area: { fill: DEFAULT_COLOR },
|
|
33
|
+
bar: { fill: DEFAULT_COLOR },
|
|
34
|
+
circle: { fill: DEFAULT_COLOR },
|
|
35
|
+
line: { stroke: DEFAULT_COLOR },
|
|
36
|
+
point: { stroke: DEFAULT_COLOR },
|
|
37
|
+
rect: { fill: DEFAULT_COLOR },
|
|
38
|
+
tick: { stroke: DEFAULT_COLOR },
|
|
39
|
+
boxplot: { fill: DEFAULT_COLOR },
|
|
40
|
+
errorbar: { stroke: DEFAULT_COLOR },
|
|
41
|
+
errorband: { fill: DEFAULT_COLOR },
|
|
42
|
+
arc: { fill: DEFAULT_COLOR },
|
|
43
|
+
background: "transparent",
|
|
44
|
+
range: {
|
|
45
|
+
category: [
|
|
46
|
+
"#5B8FF9",
|
|
47
|
+
"#61DDAA",
|
|
48
|
+
"#65789B",
|
|
49
|
+
"#F6BD16",
|
|
50
|
+
"#7262FD",
|
|
51
|
+
"#78D3F8",
|
|
52
|
+
"#9661BC",
|
|
53
|
+
"#F6903D",
|
|
54
|
+
"#008685",
|
|
55
|
+
"#F08BB4",
|
|
56
|
+
],
|
|
57
|
+
diverging: ["#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
|
|
58
|
+
heatmap: ["#000000", "#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
|
|
59
|
+
ramp: [
|
|
60
|
+
"#EBCCFF",
|
|
61
|
+
"#CCB0FF",
|
|
62
|
+
"#AE95FF",
|
|
63
|
+
"#907BFF",
|
|
64
|
+
"#7262FD",
|
|
65
|
+
"#5349E0",
|
|
66
|
+
"#2F32C3",
|
|
67
|
+
"#001BA7",
|
|
68
|
+
"#00068C"
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
scale: {
|
|
72
|
+
continuous: { range: ["#f7fbff", "#08306b"] },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
dark: {
|
|
76
|
+
...DARK_COMMON_DESIGN,
|
|
77
|
+
area: { fill: DEFAULT_COLOR },
|
|
78
|
+
bar: { fill: DEFAULT_COLOR },
|
|
79
|
+
circle: { fill: DEFAULT_COLOR },
|
|
80
|
+
line: { stroke: DEFAULT_COLOR },
|
|
81
|
+
point: { stroke: DEFAULT_COLOR },
|
|
82
|
+
rect: { fill: DEFAULT_COLOR },
|
|
83
|
+
tick: { stroke: DEFAULT_COLOR },
|
|
84
|
+
boxplot: { fill: DEFAULT_COLOR },
|
|
85
|
+
errorbar: { stroke: DEFAULT_COLOR },
|
|
86
|
+
errorband: { fill: DEFAULT_COLOR },
|
|
87
|
+
arc: { fill: DEFAULT_COLOR },
|
|
88
|
+
range: {
|
|
89
|
+
category: [
|
|
90
|
+
"#5B8FF9",
|
|
91
|
+
"#61DDAA",
|
|
92
|
+
"#65789B",
|
|
93
|
+
"#F6BD16",
|
|
94
|
+
"#7262FD",
|
|
95
|
+
"#78D3F8",
|
|
96
|
+
"#9661BC",
|
|
97
|
+
"#F6903D",
|
|
98
|
+
"#008685",
|
|
99
|
+
"#F08BB4",
|
|
100
|
+
],
|
|
101
|
+
diverging: ["#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
|
|
102
|
+
heatmap: ["#000000", "#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
|
|
103
|
+
ramp: [
|
|
104
|
+
"#EBCCFF",
|
|
105
|
+
"#CCB0FF",
|
|
106
|
+
"#AE95FF",
|
|
107
|
+
"#907BFF",
|
|
108
|
+
"#7262FD",
|
|
109
|
+
"#5349E0",
|
|
110
|
+
"#2F32C3",
|
|
111
|
+
"#001BA7",
|
|
112
|
+
"#00068C"
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
scale: {
|
|
116
|
+
continuous: { range: ["#f7fbff", "#08306b"] },
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
} as const;
|
|
120
|
+
|
|
121
|
+
export const builtInThemes: { [themeKey: string]: { light: any; dark: any; } } = {
|
|
122
|
+
vega: VegaTheme,
|
|
123
|
+
g2: AntVTheme,
|
|
124
|
+
};
|
|
@@ -29,34 +29,14 @@ import { useTranslation } from 'react-i18next';
|
|
|
29
29
|
import { ResizeDialog } from '../components/sizeSetting';
|
|
30
30
|
import { GEMO_TYPES, STACK_MODE, CHART_LAYOUT_TYPE } from '../config';
|
|
31
31
|
import { useGlobalStore } from '../store';
|
|
32
|
-
import { IStackMode, EXPLORATION_TYPES, IBrushDirection, BRUSH_DIRECTIONS } from '../interfaces';
|
|
32
|
+
import { IStackMode, EXPLORATION_TYPES, IBrushDirection, BRUSH_DIRECTIONS, IDarkMode } from '../interfaces';
|
|
33
33
|
import { IReactVegaHandler } from '../vis/react-vega';
|
|
34
34
|
import Toolbar, { ToolbarItemProps } from '../components/toolbar';
|
|
35
35
|
import { ButtonWithShortcut } from './menubar';
|
|
36
|
+
import { useCurrentMediaTheme } from '../utils/media';
|
|
36
37
|
import throttle from '../utils/throttle';
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
export const LiteContainer = styled.div`
|
|
40
|
-
margin: 0.2em;
|
|
41
|
-
border: 1px solid #e5e7eb;
|
|
42
|
-
padding: 1em;
|
|
43
|
-
background-color: #fff;
|
|
44
|
-
.menu-root {
|
|
45
|
-
position: relative;
|
|
46
|
-
& > *:not(.trigger) {
|
|
47
|
-
display: flex;
|
|
48
|
-
flex-direction: column;
|
|
49
|
-
position: absolute;
|
|
50
|
-
right: 0;
|
|
51
|
-
top: 100%;
|
|
52
|
-
border: 1px solid #8884;
|
|
53
|
-
}
|
|
54
|
-
&:not(:hover) > *:not(.trigger):not(:hover) {
|
|
55
|
-
display: none;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
`;
|
|
59
|
-
|
|
60
40
|
const Invisible = styled.div`
|
|
61
41
|
clip: rect(1px, 1px, 1px, 1px);
|
|
62
42
|
clip-path: inset(50%);
|
|
@@ -74,13 +54,18 @@ const FormContainer = styled.div`
|
|
|
74
54
|
padding: 0.5em;
|
|
75
55
|
display: flex;
|
|
76
56
|
flex-direction: column;
|
|
57
|
+
color: #444;
|
|
58
|
+
.dark {
|
|
59
|
+
color: #aaa;
|
|
60
|
+
}
|
|
77
61
|
`;
|
|
78
62
|
|
|
79
63
|
interface IVisualSettings {
|
|
64
|
+
darkModePreference: IDarkMode;
|
|
80
65
|
rendererHandler?: React.RefObject<IReactVegaHandler>;
|
|
81
66
|
}
|
|
82
67
|
|
|
83
|
-
const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler }) => {
|
|
68
|
+
const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler, darkModePreference }) => {
|
|
84
69
|
const { vizStore } = useGlobalStore();
|
|
85
70
|
const { visualConfig, canUndo, canRedo } = vizStore;
|
|
86
71
|
const { t: tGlobal } = useTranslation();
|
|
@@ -99,6 +84,8 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler }) => {
|
|
|
99
84
|
rendererHandler?.current?.downloadSVG();
|
|
100
85
|
}, 200), [rendererHandler]);
|
|
101
86
|
|
|
87
|
+
const dark = useCurrentMediaTheme(darkModePreference) === 'dark';
|
|
88
|
+
|
|
102
89
|
const items = useMemo<ToolbarItemProps[]>(() => {
|
|
103
90
|
return [
|
|
104
91
|
{
|
|
@@ -153,6 +140,11 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler }) => {
|
|
|
153
140
|
key: 'mark_type',
|
|
154
141
|
label: tGlobal('constant.mark_type.__enum__'),
|
|
155
142
|
icon: StopIcon,
|
|
143
|
+
styles: {
|
|
144
|
+
icon: {
|
|
145
|
+
color: 'rgb(294,115,22)',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
156
148
|
options: GEMO_TYPES.map(g => ({
|
|
157
149
|
key: g,
|
|
158
150
|
label: tGlobal(`constant.mark_type.${g}`),
|
|
@@ -325,16 +317,16 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler }) => {
|
|
|
325
317
|
label: t('button.export_chart'),
|
|
326
318
|
icon: PhotoIcon,
|
|
327
319
|
form: (
|
|
328
|
-
<FormContainer>
|
|
320
|
+
<FormContainer className={dark ? 'dark' : ''}>
|
|
329
321
|
<button
|
|
330
|
-
className=
|
|
322
|
+
className={`text-xs pt-1 pb-1 pl-6 pr-6 ${dark ? 'dark bg-zinc-900 text-gray-100 hover:bg-gray-700' : 'bg-white hover:bg-gray-200 text-gray-800'}`}
|
|
331
323
|
aria-label={t('button.export_chart_as', { type: 'png' })}
|
|
332
324
|
onClick={() => downloadPNG()}
|
|
333
325
|
>
|
|
334
326
|
{t('button.export_chart_as', { type: 'png' })}
|
|
335
327
|
</button>
|
|
336
328
|
<button
|
|
337
|
-
className=
|
|
329
|
+
className={`text-xs pt-1 pb-1 pl-6 pr-6 ${dark ? 'dark bg-zinc-900 text-gray-100 hover:bg-gray-700' : 'bg-white hover:bg-gray-200 text-gray-800'}`}
|
|
338
330
|
aria-label={t('button.export_chart_as', { type: 'svg' })}
|
|
339
331
|
onClick={() => downloadSVG()}
|
|
340
332
|
>
|
|
@@ -343,24 +335,28 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler }) => {
|
|
|
343
335
|
</FormContainer>
|
|
344
336
|
),
|
|
345
337
|
},
|
|
346
|
-
];
|
|
347
|
-
}, [vizStore, canUndo, canRedo, defaultAggregated, markType, stack, interactiveScale, sizeMode, width, height, explorationMode, brushDirection, showActions, downloadPNG, downloadSVG]);
|
|
338
|
+
] as ToolbarItemProps[];
|
|
339
|
+
}, [vizStore, canUndo, canRedo, defaultAggregated, markType, stack, interactiveScale, sizeMode, width, height, explorationMode, brushDirection, showActions, downloadPNG, downloadSVG, dark]);
|
|
348
340
|
|
|
349
341
|
return <div style={{ margin: '0.38em 0.28em 0.2em 0.18em' }}>
|
|
350
342
|
<Toolbar
|
|
343
|
+
darkModePreference={darkModePreference}
|
|
351
344
|
items={items}
|
|
352
345
|
styles={{
|
|
353
346
|
root: {
|
|
354
347
|
'--background-color': '#fff',
|
|
348
|
+
'--dark-background-color': '#000',
|
|
355
349
|
'--color': '#777',
|
|
356
350
|
'--color-hover': '#555',
|
|
357
|
-
'--
|
|
358
|
-
'--
|
|
351
|
+
'--dark-color': '#999',
|
|
352
|
+
'--dark-color-hover': '#bbb',
|
|
353
|
+
'--blue': 'rgb(79,70,229)',
|
|
354
|
+
'--blue-dark': 'rgb(9, 6, 65)',
|
|
359
355
|
},
|
|
360
356
|
container: {
|
|
361
|
-
border: '1px solid #e5e7eb',
|
|
362
|
-
boxSizing: 'content-box',
|
|
363
|
-
borderRadius: '1px',
|
|
357
|
+
// border: '1px solid #e5e7eb',
|
|
358
|
+
// boxSizing: 'content-box',
|
|
359
|
+
// borderRadius: '1px',
|
|
364
360
|
},
|
|
365
361
|
}}
|
|
366
362
|
/>
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import styled from "styled-components";
|
|
2
|
-
|
|
3
|
-
export const Container = styled.div`
|
|
4
|
-
border: 1px solid #e5e7eb;
|
|
5
|
-
padding: 1em;
|
|
6
|
-
margin: 1em;
|
|
7
|
-
background-color: #fff;
|
|
8
|
-
`;
|
|
9
|
-
|
|
10
|
-
export const NestContainer = styled.div`
|
|
11
|
-
border: 1px solid #e5e7eb;
|
|
12
|
-
padding: 0.4em;
|
|
13
|
-
font-size: 12px;
|
|
14
|
-
margin: 0.2em;
|
|
15
|
-
background-color: #fff;
|
|
16
|
-
`;
|