@kanaries/graphic-walker 0.2.13 → 0.2.14

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 (87) hide show
  1. package/dist/App.d.ts +4 -2
  2. package/dist/assets/explainer.worker-8428eb12.js.map +1 -1
  3. package/dist/components/button/base.d.ts +1 -0
  4. package/dist/components/button/defaultMini.d.ts +4 -0
  5. package/dist/components/button/primaryMini.d.ts +4 -0
  6. package/dist/components/dropdownContext/index.d.ts +13 -0
  7. package/dist/components/dropdownSelect/index.d.ts +17 -0
  8. package/dist/components/modal.d.ts +1 -0
  9. package/dist/components/toolbar/toolbar-item.d.ts +1 -0
  10. package/dist/dataSource/dataSelection/config.d.ts +2 -0
  11. package/dist/dataSource/index.d.ts +1 -1
  12. package/dist/fields/datasetFields/dimFields.d.ts +2 -2
  13. package/dist/fields/datasetFields/meaFields.d.ts +2 -2
  14. package/dist/fields/encodeFields/singleEncodeDropDown.d.ts +17 -0
  15. package/dist/fields/encodeFields/singleEncodeEditor.d.ts +11 -0
  16. package/dist/fields/obComponents/obPill.d.ts +3 -3
  17. package/dist/graphic-walker.es.js +20874 -19172
  18. package/dist/graphic-walker.es.js.map +1 -1
  19. package/dist/graphic-walker.umd.js +245 -170
  20. package/dist/graphic-walker.umd.js.map +1 -1
  21. package/dist/insightBoard/index.d.ts +1 -1
  22. package/dist/interfaces.d.ts +1 -0
  23. package/dist/renderer/index.d.ts +3 -1
  24. package/dist/store/visualSpecStore.d.ts +1 -0
  25. package/dist/utils/index.d.ts +2 -0
  26. package/dist/utils/media.d.ts +2 -0
  27. package/dist/vis/react-vega.d.ts +2 -0
  28. package/dist/vis/theme.d.ts +130 -0
  29. package/package.json +2 -1
  30. package/src/App.tsx +8 -5
  31. package/src/components/button/base.ts +1 -0
  32. package/src/components/button/default.tsx +6 -2
  33. package/src/components/button/defaultMini.tsx +17 -0
  34. package/src/components/button/primary.tsx +6 -2
  35. package/src/components/button/primaryMini.tsx +21 -0
  36. package/src/components/callout.tsx +4 -1
  37. package/src/components/clickMenu.tsx +4 -2
  38. package/src/components/container.tsx +9 -0
  39. package/src/components/dataTable/index.tsx +42 -52
  40. package/src/components/dataTable/pagination.tsx +4 -4
  41. package/src/components/dataTypeIcon.tsx +1 -1
  42. package/src/components/dropdownContext/index.tsx +64 -0
  43. package/src/components/dropdownSelect/index.tsx +92 -0
  44. package/src/components/modal.tsx +26 -14
  45. package/src/components/tabs/defaultTab.tsx +4 -4
  46. package/src/components/tabs/editableTab.tsx +5 -5
  47. package/src/components/toolbar/components.tsx +18 -1
  48. package/src/components/toolbar/index.tsx +5 -0
  49. package/src/components/toolbar/toolbar-button.tsx +6 -1
  50. package/src/components/toolbar/toolbar-item.tsx +4 -0
  51. package/src/components/toolbar/toolbar-select-button.tsx +21 -4
  52. package/src/components/toolbar/toolbar-toggle-button.tsx +6 -1
  53. package/src/components/tooltip.tsx +4 -1
  54. package/src/dataSource/dataSelection/config.ts +28 -0
  55. package/src/dataSource/dataSelection/csvData.tsx +77 -32
  56. package/src/dataSource/dataSelection/gwFile.tsx +0 -8
  57. package/src/dataSource/dataSelection/index.tsx +1 -2
  58. package/src/dataSource/dataSelection/publicData.tsx +2 -3
  59. package/src/dataSource/index.tsx +81 -61
  60. package/src/fields/aestheticFields.tsx +3 -1
  61. package/src/fields/components.tsx +21 -2
  62. package/src/fields/datasetFields/dimFields.tsx +43 -35
  63. package/src/fields/datasetFields/index.tsx +2 -2
  64. package/src/fields/datasetFields/meaFields.tsx +73 -47
  65. package/src/fields/encodeFields/singleEncodeDropDown.tsx +92 -0
  66. package/src/fields/encodeFields/singleEncodeEditor.tsx +78 -0
  67. package/src/fields/filterField/filterEditDialog.tsx +2 -1
  68. package/src/fields/filterField/filterPill.tsx +1 -1
  69. package/src/fields/filterField/slider.tsx +1 -1
  70. package/src/fields/filterField/tabs.tsx +11 -21
  71. package/src/fields/obComponents/obPill.tsx +65 -35
  72. package/src/index.css +13 -0
  73. package/src/insightBoard/index.tsx +24 -23
  74. package/src/insightBoard/radioGroupButtons.tsx +7 -0
  75. package/src/interfaces.ts +1 -0
  76. package/src/lib/inferMeta.ts +1 -1
  77. package/src/locales/en-US.json +7 -4
  78. package/src/locales/zh-CN.json +5 -2
  79. package/src/main.tsx +1 -1
  80. package/src/renderer/index.tsx +2 -1
  81. package/src/store/visualSpecStore.ts +16 -0
  82. package/src/utils/index.ts +19 -0
  83. package/src/utils/media.ts +26 -0
  84. package/src/utils/normalization.ts +2 -1
  85. package/src/vis/react-vega.tsx +20 -4
  86. package/src/vis/theme.ts +126 -0
  87. package/src/visualSettings/index.tsx +24 -8
@@ -11,6 +11,8 @@ import { COUNT_FIELD_ID } from '../constants';
11
11
  import { IViewField, IRow, IStackMode } 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,8 @@ 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?: 'vega' | 'g2';
49
53
  }
50
54
  const NULL_FIELD: IViewField = {
51
55
  dragId: '',
@@ -119,7 +123,15 @@ function channelEncode(props: EncodeProps) {
119
123
  encoding[c] = {
120
124
  field: props[c].fid,
121
125
  title: props[c].name,
122
- type: props[c].semanticType
126
+ type: props[c].semanticType,
127
+ }
128
+ if (props[c].analyticType !== 'measure') {
129
+ // if `aggregate` is set to null,
130
+ // do not aggregate this field
131
+ encoding[c].aggregate = null;
132
+ }
133
+ if (props[c].analyticType === 'measure') {
134
+ encoding[c].type = 'quantitative'
123
135
  }
124
136
  }
125
137
  })
@@ -143,7 +155,7 @@ function channelEncode(props: EncodeProps) {
143
155
  }
144
156
  function channelAggregate(encoding: {[key: string]: any}, fields: IViewField[]) {
145
157
  Object.values(encoding).forEach(c => {
146
- const targetField = fields.find(f => f.fid === c.field);
158
+ const targetField = fields.find(f => f.fid === c.field && !('aggregate' in c));
147
159
  if (targetField && targetField.fid === COUNT_FIELD_ID) {
148
160
  c.field = undefined;
149
161
  c.aggregate = 'count';
@@ -378,11 +390,14 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
378
390
  height,
379
391
  selectEncoding,
380
392
  brushEncoding,
393
+ themeKey = 'vega',
381
394
  } = props;
382
395
  // const container = useRef<HTMLDivElement>(null);
383
396
  // const containers = useRef<(HTMLDivElement | null)[]>([]);
384
397
  const [viewPlaceholders, setViewPlaceholders] = useState<React.MutableRefObject<HTMLDivElement>[]>([]);
385
398
  const { i18n } = useTranslation();
399
+ const mediaTheme = useCurrentMediaTheme();
400
+ const themeConfig = builtInThemes[themeKey]?.[mediaTheme];
386
401
  useEffect(() => {
387
402
  const clickSub = geomClick$.subscribe(([values, e]) => {
388
403
  if (onGeomClick) {
@@ -502,7 +517,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
502
517
  spec.params.push(...singleView.params!);
503
518
  }
504
519
  if (viewPlaceholders.length > 0 && viewPlaceholders[0].current) {
505
- embed(viewPlaceholders[0].current, spec, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language) }).then(res => {
520
+ embed(viewPlaceholders[0].current, spec, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config: themeConfig }).then(res => {
506
521
  vegaRefs.current = [res.view];
507
522
  try {
508
523
  res.view.addEventListener('click', (e) => {
@@ -583,7 +598,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
583
598
  ans.params = commonSpec.params;
584
599
  }
585
600
  if (node) {
586
- embed(node, ans, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language) }).then(res => {
601
+ embed(node, ans, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config: themeConfig }).then(res => {
587
602
  vegaRefs.current.push(res.view);
588
603
  const paramStores = (res.vgSpec.data?.map(d => d.name) ?? []).filter(
589
604
  name => [BRUSH_SIGNAL_NAME, POINT_SIGNAL_NAME].map(p => `${p}_store`).includes(name)
@@ -673,6 +688,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
673
688
  selectEncoding,
674
689
  brushEncoding,
675
690
  crossFilterTriggerIdx,
691
+ themeConfig,
676
692
  ]);
677
693
 
678
694
  useImperativeHandle(ref, () => ({
@@ -0,0 +1,126 @@
1
+ const DEFAULT_COLOR = "#5B8FF9";
2
+
3
+ export const VegaTheme = {
4
+ light: {
5
+ background: "transparent",
6
+ },
7
+ dark: {
8
+ background: "transparent",
9
+ axis: {
10
+ gridColor: "#666",
11
+ domainColor: "#d1d5db", // change axis color to white
12
+ tickColor: "#d1d5db", // change tick color to white
13
+ labelColor: "#d1d5db", // change label 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
+ },
20
+ } as const;
21
+
22
+ export const AntVTheme = {
23
+ light: {
24
+ area: { fill: DEFAULT_COLOR },
25
+ bar: { fill: DEFAULT_COLOR },
26
+ circle: { fill: DEFAULT_COLOR },
27
+ line: { stroke: DEFAULT_COLOR },
28
+ point: { stroke: DEFAULT_COLOR },
29
+ rect: { fill: DEFAULT_COLOR },
30
+ tick: { stroke: DEFAULT_COLOR },
31
+ boxplot: { fill: DEFAULT_COLOR },
32
+ errorbar: { stroke: DEFAULT_COLOR },
33
+ errorband: { fill: DEFAULT_COLOR },
34
+ arc: { fill: DEFAULT_COLOR },
35
+ background: "transparent",
36
+ range: {
37
+ category: [
38
+ "#5B8FF9",
39
+ "#61DDAA",
40
+ "#65789B",
41
+ "#F6BD16",
42
+ "#7262FD",
43
+ "#78D3F8",
44
+ "#9661BC",
45
+ "#F6903D",
46
+ "#008685",
47
+ "#F08BB4",
48
+ ],
49
+ diverging: ["#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
50
+ heatmap: ["#000000", "#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
51
+ ramp: [
52
+ "#EBCCFF",
53
+ "#CCB0FF",
54
+ "#AE95FF",
55
+ "#907BFF",
56
+ "#7262FD",
57
+ "#5349E0",
58
+ "#2F32C3",
59
+ "#001BA7",
60
+ "#00068C"
61
+ ],
62
+ },
63
+ scale: {
64
+ continuous: { range: ["#f7fbff", "#08306b"] },
65
+ },
66
+ },
67
+ dark: {
68
+ area: { fill: DEFAULT_COLOR },
69
+ bar: { fill: DEFAULT_COLOR },
70
+ circle: { fill: DEFAULT_COLOR },
71
+ line: { stroke: DEFAULT_COLOR },
72
+ point: { stroke: DEFAULT_COLOR },
73
+ rect: { fill: DEFAULT_COLOR },
74
+ tick: { stroke: DEFAULT_COLOR },
75
+ boxplot: { fill: DEFAULT_COLOR },
76
+ errorbar: { stroke: DEFAULT_COLOR },
77
+ errorband: { fill: DEFAULT_COLOR },
78
+ arc: { fill: DEFAULT_COLOR },
79
+ background: "transparent", // change background color to dark gray
80
+ axis: {
81
+ gridColor: "#666",
82
+ domainColor: "#d1d5db", // change axis color to white
83
+ tickColor: "#d1d5db", // change tick color to white
84
+ labelColor: "#d1d5db", // change label color to white
85
+ },
86
+ legend: {
87
+ labelColor: "#d1d5db", // change legend label color to white
88
+ titleColor: "#d1d5db" // change legend title color to white
89
+ },
90
+ range: {
91
+ category: [
92
+ "#5B8FF9",
93
+ "#61DDAA",
94
+ "#65789B",
95
+ "#F6BD16",
96
+ "#7262FD",
97
+ "#78D3F8",
98
+ "#9661BC",
99
+ "#F6903D",
100
+ "#008685",
101
+ "#F08BB4",
102
+ ],
103
+ diverging: ["#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
104
+ heatmap: ["#000000", "#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"],
105
+ ramp: [
106
+ "#EBCCFF",
107
+ "#CCB0FF",
108
+ "#AE95FF",
109
+ "#907BFF",
110
+ "#7262FD",
111
+ "#5349E0",
112
+ "#2F32C3",
113
+ "#001BA7",
114
+ "#00068C"
115
+ ],
116
+ },
117
+ scale: {
118
+ continuous: { range: ["#f7fbff", "#08306b"] },
119
+ },
120
+ },
121
+ } as const;
122
+
123
+ export const builtInThemes: { [themeKey: string]: { light: any; dark: any; } } = {
124
+ vega: VegaTheme,
125
+ g2: AntVTheme,
126
+ };
@@ -41,6 +41,10 @@ export const LiteContainer = styled.div`
41
41
  border: 1px solid #e5e7eb;
42
42
  padding: 1em;
43
43
  background-color: #fff;
44
+ @media (prefers-color-scheme: dark) {
45
+ background-color: #000;
46
+ border: 1px solid #4b5563;
47
+ }
44
48
  .menu-root {
45
49
  position: relative;
46
50
  & > *:not(.trigger) {
@@ -74,6 +78,10 @@ const FormContainer = styled.div`
74
78
  padding: 0.5em;
75
79
  display: flex;
76
80
  flex-direction: column;
81
+ color: #444;
82
+ @media (prefers-color-scheme: dark) {
83
+ color: #aaa;
84
+ }
77
85
  `;
78
86
 
79
87
  interface IVisualSettings {
@@ -153,6 +161,11 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler }) => {
153
161
  key: 'mark_type',
154
162
  label: tGlobal('constant.mark_type.__enum__'),
155
163
  icon: StopIcon,
164
+ styles: {
165
+ icon: {
166
+ color: 'rgb(294,115,22)',
167
+ },
168
+ },
156
169
  options: GEMO_TYPES.map(g => ({
157
170
  key: g,
158
171
  label: tGlobal(`constant.mark_type.${g}`),
@@ -327,14 +340,14 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler }) => {
327
340
  form: (
328
341
  <FormContainer>
329
342
  <button
330
- className="text-xs pt-1 pb-1 pl-6 pr-6 bg-white hover:bg-gray-200"
343
+ className="text-xs pt-1 pb-1 pl-6 pr-6 bg-white dark:bg-zinc-900 hover:bg-gray-200 text-gray-800 dark:text-gray-100 dark:hover:bg-gray-700"
331
344
  aria-label={t('button.export_chart_as', { type: 'png' })}
332
345
  onClick={() => downloadPNG()}
333
346
  >
334
347
  {t('button.export_chart_as', { type: 'png' })}
335
348
  </button>
336
349
  <button
337
- className="text-xs pt-1 pb-1 pl-6 pr-6 bg-white hover:bg-gray-200"
350
+ className="text-xs pt-1 pb-1 pl-6 pr-6 bg-white dark:bg-zinc-900 hover:bg-gray-200 text-gray-800 dark:text-gray-100 dark:hover:bg-gray-700"
338
351
  aria-label={t('button.export_chart_as', { type: 'svg' })}
339
352
  onClick={() => downloadSVG()}
340
353
  >
@@ -343,7 +356,7 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler }) => {
343
356
  </FormContainer>
344
357
  ),
345
358
  },
346
- ];
359
+ ] as ToolbarItemProps[];
347
360
  }, [vizStore, canUndo, canRedo, defaultAggregated, markType, stack, interactiveScale, sizeMode, width, height, explorationMode, brushDirection, showActions, downloadPNG, downloadSVG]);
348
361
 
349
362
  return <div style={{ margin: '0.38em 0.28em 0.2em 0.18em' }}>
@@ -352,15 +365,18 @@ const VisualSettings: React.FC<IVisualSettings> = ({ rendererHandler }) => {
352
365
  styles={{
353
366
  root: {
354
367
  '--background-color': '#fff',
368
+ '--dark-background-color': '#000',
355
369
  '--color': '#777',
356
370
  '--color-hover': '#555',
357
- '--blue': '#282958',
358
- '--blue-dark': '#1d1e38',
371
+ '--dark-color': '#999',
372
+ '--dark-color-hover': '#bbb',
373
+ '--blue': 'rgb(79,70,229)',
374
+ '--blue-dark': 'rgb(9, 6, 65)',
359
375
  },
360
376
  container: {
361
- border: '1px solid #e5e7eb',
362
- boxSizing: 'content-box',
363
- borderRadius: '1px',
377
+ // border: '1px solid #e5e7eb',
378
+ // boxSizing: 'content-box',
379
+ // borderRadius: '1px',
364
380
  },
365
381
  }}
366
382
  />