@kanaries/graphic-walker 0.2.14 → 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 (128) hide show
  1. package/dist/App.d.ts +5 -2
  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/callout.d.ts +2 -0
  6. package/dist/components/codeExport/index.d.ts +3 -0
  7. package/dist/components/loadingLayer.d.ts +2 -0
  8. package/dist/components/tabs/defaultTab.d.ts +1 -0
  9. package/dist/components/tabs/editableTab.d.ts +1 -2
  10. package/dist/components/toolbar/components.d.ts +4 -1
  11. package/dist/components/toolbar/index.d.ts +2 -0
  12. package/dist/components/toolbar/toolbar-item.d.ts +3 -0
  13. package/dist/components/tooltip.d.ts +2 -0
  14. package/dist/dataSource/dataSelection/config.d.ts +1 -0
  15. package/dist/dataSource/dataSelection/utils.d.ts +2 -0
  16. package/dist/datasets/tmp/test.json +1 -0
  17. package/dist/fields/components.d.ts +0 -1
  18. package/dist/fields/filterField/filterEditDialog.d.ts +1 -1
  19. package/dist/graphic-walker.es.js +23930 -23320
  20. package/dist/graphic-walker.es.js.map +1 -1
  21. package/dist/graphic-walker.umd.js +143 -273
  22. package/dist/graphic-walker.umd.js.map +1 -1
  23. package/dist/index.d.ts +3 -3
  24. package/dist/interfaces.d.ts +23 -1
  25. package/dist/lib/execExp.d.ts +8 -0
  26. package/dist/lib/interfaces.d.ts +22 -0
  27. package/dist/lib/op/aggregate.d.ts +3 -0
  28. package/dist/lib/op/bin.d.ts +3 -0
  29. package/dist/lib/op/fold.d.ts +3 -0
  30. package/dist/lib/op/stat.d.ts +8 -0
  31. package/dist/lib/viewQuery.d.ts +5 -0
  32. package/dist/models/visSpecHistory.d.ts +2 -0
  33. package/dist/renderer/index.d.ts +6 -3
  34. package/dist/renderer/specRenderer.d.ts +13 -0
  35. package/dist/services.d.ts +4 -1
  36. package/dist/store/commonStore.d.ts +6 -0
  37. package/dist/store/index.d.ts +3 -2
  38. package/dist/store/visualSpecStore.d.ts +11 -4
  39. package/dist/utils/dataPrep.d.ts +2 -0
  40. package/dist/utils/index.d.ts +3 -5
  41. package/dist/utils/media.d.ts +2 -1
  42. package/dist/utils/save.d.ts +1 -2
  43. package/dist/vis/react-vega.d.ts +4 -23
  44. package/dist/vis/spec/aggregate.d.ts +4 -0
  45. package/dist/vis/spec/encode.d.ts +19 -0
  46. package/dist/vis/spec/field.d.ts +2 -0
  47. package/dist/vis/spec/mark.d.ts +7 -0
  48. package/dist/vis/spec/stack.d.ts +4 -0
  49. package/dist/vis/spec/view.d.ts +67 -0
  50. package/dist/vis/theme.d.ts +36 -20
  51. package/dist/visualSettings/index.d.ts +2 -1
  52. package/dist/workers/transform.d.ts +2 -0
  53. package/package.json +4 -3
  54. package/src/App.tsx +23 -15
  55. package/src/components/callout.tsx +9 -7
  56. package/src/components/clickMenu.tsx +1 -7
  57. package/src/components/codeExport/index.tsx +114 -0
  58. package/src/components/dataTable/index.tsx +10 -10
  59. package/src/components/loadingLayer.tsx +7 -0
  60. package/src/components/modal.tsx +1 -15
  61. package/src/components/sizeSetting.tsx +2 -2
  62. package/src/components/tabs/defaultTab.tsx +4 -2
  63. package/src/components/tabs/editableTab.tsx +75 -40
  64. package/src/components/toolbar/components.tsx +8 -23
  65. package/src/components/toolbar/index.tsx +11 -4
  66. package/src/components/toolbar/toolbar-button.tsx +2 -1
  67. package/src/components/toolbar/toolbar-item.tsx +17 -12
  68. package/src/components/toolbar/toolbar-select-button.tsx +9 -13
  69. package/src/components/toolbar/toolbar-toggle-button.tsx +2 -1
  70. package/src/components/tooltip.tsx +10 -6
  71. package/src/dataSource/dataSelection/config.ts +11 -0
  72. package/src/dataSource/dataSelection/csvData.tsx +72 -40
  73. package/src/dataSource/dataSelection/gwFile.tsx +2 -2
  74. package/src/dataSource/dataSelection/utils.ts +28 -0
  75. package/src/dataSource/index.tsx +2 -3
  76. package/src/dataSource/utils.ts +8 -3
  77. package/src/fields/components.tsx +13 -50
  78. package/src/fields/datasetFields/index.tsx +3 -4
  79. package/src/fields/datasetFields/meaFields.tsx +12 -4
  80. package/src/fields/encodeFields/singleEncodeEditor.tsx +1 -1
  81. package/src/fields/filterField/filterEditDialog.tsx +63 -99
  82. package/src/fields/filterField/slider.tsx +1 -1
  83. package/src/index.css +4 -4
  84. package/src/index.tsx +22 -22
  85. package/src/insightBoard/mainBoard.tsx +9 -2
  86. package/src/interfaces.ts +30 -3
  87. package/src/lib/execExp.ts +147 -0
  88. package/src/lib/interfaces.ts +39 -0
  89. package/src/lib/op/aggregate.ts +49 -0
  90. package/src/lib/op/bin.ts +25 -0
  91. package/src/lib/op/fold.ts +17 -0
  92. package/src/lib/op/stat.ts +46 -0
  93. package/src/lib/viewQuery.ts +23 -0
  94. package/src/locales/en-US.json +8 -3
  95. package/src/locales/i18n.ts +7 -1
  96. package/src/locales/ja-JP.json +197 -0
  97. package/src/locales/zh-CN.json +8 -3
  98. package/src/main.tsx +1 -1
  99. package/src/models/visSpecHistory.ts +14 -0
  100. package/src/renderer/index.tsx +58 -101
  101. package/src/renderer/specRenderer.tsx +119 -0
  102. package/src/segments/segmentNav.tsx +3 -16
  103. package/src/segments/visNav.tsx +17 -6
  104. package/src/services.ts +37 -1
  105. package/src/store/commonStore.ts +14 -9
  106. package/src/store/index.tsx +11 -4
  107. package/src/store/visualSpecStore.ts +89 -50
  108. package/src/utils/dataPrep.ts +24 -0
  109. package/src/utils/index.ts +16 -17
  110. package/src/utils/media.ts +16 -11
  111. package/src/utils/normalization.ts +3 -1
  112. package/src/utils/save.ts +1 -2
  113. package/src/vis/react-vega.tsx +11 -332
  114. package/src/vis/spec/aggregate.ts +13 -0
  115. package/src/vis/spec/encode.ts +69 -0
  116. package/src/vis/spec/field.ts +10 -0
  117. package/src/vis/spec/mark.ts +30 -0
  118. package/src/vis/spec/stack.ts +11 -0
  119. package/src/vis/spec/view.ts +138 -0
  120. package/src/vis/theme.ts +35 -25
  121. package/src/visualSettings/index.tsx +22 -33
  122. package/src/workers/transform.ts +12 -0
  123. package/src/workers/transform.worker.js +13 -0
  124. package/src/workers/viewQuery.worker.js +16 -0
  125. package/dist/components/container.d.ts +0 -2
  126. package/dist/dataSource/pannel.d.ts +0 -5
  127. package/src/components/container.tsx +0 -25
  128. package/src/dataSource/pannel.tsx +0 -71
@@ -3,38 +3,13 @@ import styled from "styled-components";
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { COLORS } from "../config";
5
5
 
6
- export const AestheticSegment = styled.div`
7
- border: 1px solid #e5e7eb;
8
- // dark mode
9
- @media (prefers-color-scheme: dark) {
10
- border: 1px solid #2d3748;
11
- }
12
- font-size: 12px;
13
- margin: 0.2em;
14
-
15
- .aes-header{
16
- border-bottom: 1px solid #e5e7eb;
17
- @media (prefers-color-scheme: dark) {
18
- border-bottom: 1px solid #2d3748;
19
- }
20
- padding: 0.6em;
21
- h4 {
22
- font-weight: 400;
23
- }
24
- }
25
- .aes-container{
26
- /* overflow-x: auto; */
27
- }
28
-
29
- `
30
-
31
6
  export const FieldListContainer: React.FC<{ name: string }> = (props) => {
32
7
  const { t } = useTranslation('translation', { keyPrefix: 'constant.draggable_key' });
33
8
 
34
9
  return (
35
- <FieldListSegment>
36
- <div className="fl-header">
37
- <h4>{t(props.name)}</h4>
10
+ <FieldListSegment className="m-0.5 border border-gray-200 dark:border-gray-700">
11
+ <div className="fl-header border-r border-gray-200 dark:border-gray-800 cursor-default select-none">
12
+ <h4 className="font-normal">{t(props.name)}</h4>
38
13
  </div>
39
14
  <div className="fl-container">{props.children}</div>
40
15
  </FieldListSegment>
@@ -45,12 +20,12 @@ export const AestheticFieldContainer: React.FC<{ name: string }> = props => {
45
20
  const { t } = useTranslation('translation', { keyPrefix: 'constant.draggable_key' });
46
21
 
47
22
  return (
48
- <AestheticSegment>
49
- <div className="aes-header cursor-default select-none">
50
- <h4>{t(props.name)}</h4>
23
+ <div className="m-0.5 text-xs border border-gray-200 dark:border-gray-700">
24
+ <div className="border-b border-gray-200 dark:border-gray-800 p-2 cursor-default select-none">
25
+ <h4 className="font-normal">{t(props.name)}</h4>
51
26
  </div>
52
- <div className="aes-container">{props.children}</div>
53
- </AestheticSegment>
27
+ <div>{props.children}</div>
28
+ </div>
54
29
  );
55
30
  }
56
31
 
@@ -58,12 +33,12 @@ export const FilterFieldContainer: React.FC = props => {
58
33
  const { t } = useTranslation('translation', { keyPrefix: 'constant.draggable_key' });
59
34
 
60
35
  return (
61
- <FilterFieldSegment>
62
- <div className="flt-header cursor-default select-none">
63
- <h4>{t('filters')}</h4>
36
+ <div className="m-0.5 text-xs border border-gray-200 dark:border-gray-700">
37
+ <div className="border-b border-gray-200 dark:border-gray-800 p-2 cursor-default select-none">
38
+ <h4 className="font-normal">{t('filters')}</h4>
64
39
  </div>
65
- <div className="flt-container">{props.children}</div>
66
- </FilterFieldSegment>
40
+ <div>{props.children}</div>
41
+ </div>
67
42
  );
68
43
  }
69
44
 
@@ -91,19 +66,11 @@ export const FilterFieldsContainer = styled.div({
91
66
 
92
67
  export const FieldListSegment = styled.div`
93
68
  display: flex;
94
- border: 1px solid #e5e7eb;
95
- @media (prefers-color-scheme: dark) {
96
- border: 1px solid #2d3748;
97
- }
98
69
  margin: 0.2em;
99
70
  font-size: 12px;
100
71
  div.fl-header {
101
72
  /* flex-basis: 100px; */
102
73
  width: 100px;
103
- border-right: 1px solid #e5e7eb;
104
- @media (prefers-color-scheme: dark) {
105
- border-right: 1px solid #2d3748;
106
- }
107
74
  flex-shrink: 0;
108
75
  h4 {
109
76
  margin: 0.6em;
@@ -112,10 +79,6 @@ export const FieldListSegment = styled.div`
112
79
  }
113
80
  div.fl-container {
114
81
  flex-grow: 10;
115
- /* display: flex;
116
- flex-wrap: wrap; */
117
- /* overflow-x: auto;
118
- overflow-y: hidden; */
119
82
  }
120
83
  `;
121
84
 
@@ -2,11 +2,10 @@ import React from "react";
2
2
  import { Droppable } from "@kanaries/react-beautiful-dnd";
3
3
  import { useTranslation } from "react-i18next";
4
4
  import styled from 'styled-components';
5
- import { NestContainer } from "../../components/container";
6
5
  import DimFields from "./dimFields";
7
6
  import MeaFields from "./meaFields";
8
7
 
9
- const DSContainer = styled(NestContainer)`
8
+ const DSContainer = styled.div`
10
9
  @media (min-width: 768px) {
11
10
  height: 680px;
12
11
  }
@@ -16,14 +15,14 @@ const DatasetFields: React.FC = (props) => {
16
15
  const { t } = useTranslation("translation", { keyPrefix: "main.tabpanel.DatasetFields" });
17
16
 
18
17
  return (
19
- <DSContainer className="border-gray-200 dark:border-gray-700 flex md:flex-col" style={{ paddingBlock: 0, paddingInline: '0.6em' }}>
18
+ <DSContainer className="p-1 m-0.5 border border-gray-200 dark:border-gray-700 flex md:flex-col" style={{ paddingBlock: 0, paddingInline: '0.6em' }}>
20
19
  <h4 className="text-xs mb-2 flex-grow-0 cursor-default select-none mt-2">{t("field_list")}</h4>
21
20
  <div className="pd-1 overflow-y-auto" style={{ maxHeight: "380px", minHeight: '100px' }}>
22
21
  <Droppable droppableId="dimensions" direction="vertical">
23
22
  {(provided, snapshot) => <DimFields provided={provided} />}
24
23
  </Droppable>
25
24
  </div>
26
- <div className="border-t dark:border-gray-800 flex-grow pd-1 overflow-y-auto">
25
+ <div className="border-t dark:border-gray-700 flex-grow pd-1 overflow-y-auto">
27
26
  <Droppable droppableId="measures" direction="vertical">
28
27
  {(provided, snapshot) => <MeaFields provided={provided} />}
29
28
  </Droppable>
@@ -20,18 +20,26 @@ const MeaFields: React.FC<Props> = (props) => {
20
20
  value: "bin",
21
21
  label: "Bin",
22
22
  },
23
+ {
24
+ value: 'binCount',
25
+ label: 'Bin Count'
26
+ },
23
27
  {
24
28
  value: "log10",
25
29
  label: "Log10",
26
30
  },
31
+ {
32
+ value: "log2",
33
+ label: "Log2",
34
+ },
27
35
  ];
28
36
  }, []);
29
37
 
30
38
  const fieldActionHandler = useCallback((selectedValue: any, opIndex: number, meaIndex: number) => {
31
- if (selectedValue === "bin") {
32
- vizStore.createBinField("measures", meaIndex);
33
- } else if (selectedValue === "log10") {
34
- vizStore.createLogField("measures", meaIndex);
39
+ if (selectedValue === "bin" || selectedValue === 'binCount') {
40
+ vizStore.createBinField("measures", meaIndex, selectedValue);
41
+ } else if (selectedValue === "log10" || selectedValue === "log2") {
42
+ vizStore.createLogField("measures", meaIndex, selectedValue);
35
43
  }
36
44
  }, []);
37
45
  return (
@@ -48,7 +48,7 @@ const SingleEncodeEditor: React.FC<SingleEncodeEditorProps> = (props) => {
48
48
  >
49
49
  <TrashIcon className="w-4" />
50
50
  </div>
51
- <div className="flex-1 flex items-center border border-gray-200 dark:border-gray-700 border-l-0 px-2 space-x-2">
51
+ <div className="flex-1 flex items-center border border-gray-200 dark:border-gray-700 border-l-0 px-2 space-x-2 truncate">
52
52
  <span className="flex-1 truncate">
53
53
  {channelItem.name}
54
54
  </span>
@@ -1,64 +1,29 @@
1
- import { CheckCircleIcon } from '@heroicons/react/24/outline';
2
- import { observer } from 'mobx-react-lite';
3
- import React from 'react';
4
- import { useTranslation } from 'react-i18next';
5
-
6
- import Modal from '../../components/modal';
7
- import type { IFilterField, IFilterRule } from '../../interfaces';
8
- import { useGlobalStore } from '../../store';
9
- import Tabs, { RuleFormProps } from './tabs';
10
-
11
-
12
- const QuantitativeRuleForm: React.FC<RuleFormProps> = ({
13
- field,
14
- onChange,
15
- }) => {
16
- return (
17
- <Tabs
18
- field={field}
19
- onChange={onChange}
20
- tabs={['range', 'one of']}
21
- />
22
- );
1
+ import { CheckCircleIcon } from "@heroicons/react/24/outline";
2
+ import { observer } from "mobx-react-lite";
3
+ import React from "react";
4
+ import { useTranslation } from "react-i18next";
5
+
6
+ import Modal from "../../components/modal";
7
+ import type { IFilterField, IFilterRule } from "../../interfaces";
8
+ import { useGlobalStore } from "../../store";
9
+ import Tabs, { RuleFormProps } from "./tabs";
10
+ import DefaultButton from "../../components/button/default";
11
+ import PrimaryButton from "../../components/button/primary";
12
+
13
+ const QuantitativeRuleForm: React.FC<RuleFormProps> = ({ field, onChange }) => {
14
+ return <Tabs field={field} onChange={onChange} tabs={["range", "one of"]} />;
23
15
  };
24
16
 
25
- const NominalRuleForm: React.FC<RuleFormProps> = ({
26
- field,
27
- onChange,
28
- }) => {
29
- return (
30
- <Tabs
31
- field={field}
32
- onChange={onChange}
33
- tabs={['one of']}
34
- />
35
- );
17
+ const NominalRuleForm: React.FC<RuleFormProps> = ({ field, onChange }) => {
18
+ return <Tabs field={field} onChange={onChange} tabs={["one of"]} />;
36
19
  };
37
20
 
38
- const OrdinalRuleForm: React.FC<RuleFormProps> = ({
39
- field,
40
- onChange,
41
- }) => {
42
- return (
43
- <Tabs
44
- field={field}
45
- onChange={onChange}
46
- tabs={['range', 'one of']}
47
- />
48
- );
21
+ const OrdinalRuleForm: React.FC<RuleFormProps> = ({ field, onChange }) => {
22
+ return <Tabs field={field} onChange={onChange} tabs={["range", "one of"]} />;
49
23
  };
50
24
 
51
- const TemporalRuleForm: React.FC<RuleFormProps> = ({
52
- field,
53
- onChange,
54
- }) => {
55
- return (
56
- <Tabs
57
- field={field}
58
- onChange={onChange}
59
- tabs={['one of', 'temporal range']}
60
- />
61
- );
25
+ const TemporalRuleForm: React.FC<RuleFormProps> = ({ field, onChange }) => {
26
+ return <Tabs field={field} onChange={onChange} tabs={["one of", "temporal range"]} />;
62
27
  };
63
28
 
64
29
  const EmptyForm: React.FC<RuleFormProps> = () => <React.Fragment />;
@@ -67,7 +32,7 @@ const FilterEditDialog: React.FC = observer(() => {
67
32
  const { vizStore } = useGlobalStore();
68
33
  const { editingFilterIdx, draggableFieldState } = vizStore;
69
34
 
70
- const { t } = useTranslation('translation', { keyPrefix: 'filters' });
35
+ const { t } = useTranslation("translation", { keyPrefix: "filters" });
71
36
 
72
37
  const field = React.useMemo(() => {
73
38
  return editingFilterIdx !== null ? draggableFieldState.filters[editingFilterIdx] : null;
@@ -83,14 +48,20 @@ const FilterEditDialog: React.FC = observer(() => {
83
48
  }
84
49
  }, [field]);
85
50
 
86
- const handleChange = React.useCallback((r: IFilterRule) => {
87
- if (editingFilterIdx !== null) {
88
- setUncontrolledField(uf => ({
89
- ...uf,
90
- rule: r,
91
- }) as IFilterField);
92
- }
93
- }, [editingFilterIdx]);
51
+ const handleChange = React.useCallback(
52
+ (r: IFilterRule) => {
53
+ if (editingFilterIdx !== null) {
54
+ setUncontrolledField(
55
+ (uf) =>
56
+ ({
57
+ ...uf,
58
+ rule: r,
59
+ } as IFilterField)
60
+ );
61
+ }
62
+ },
63
+ [editingFilterIdx]
64
+ );
94
65
 
95
66
  const handleSubmit = React.useCallback(() => {
96
67
  if (editingFilterIdx !== null) {
@@ -100,45 +71,38 @@ const FilterEditDialog: React.FC = observer(() => {
100
71
  vizStore.closeFilterEditing();
101
72
  }, [editingFilterIdx, uncontrolledField]);
102
73
 
103
- const Form = field ? ({
104
- quantitative: QuantitativeRuleForm,
105
- nominal: NominalRuleForm,
106
- ordinal: OrdinalRuleForm,
107
- temporal: TemporalRuleForm,
108
- }[field.semanticType] as React.FC<RuleFormProps>) : EmptyForm;
109
-
74
+ const Form = field
75
+ ? ({
76
+ quantitative: QuantitativeRuleForm,
77
+ nominal: NominalRuleForm,
78
+ ordinal: OrdinalRuleForm,
79
+ temporal: TemporalRuleForm,
80
+ }[field.semanticType] as React.FC<RuleFormProps>)
81
+ : EmptyForm;
82
+
110
83
  return uncontrolledField ? (
111
- <Modal
112
- show={Boolean(uncontrolledField)}
113
- title={t('editing')}
114
- onClose={() => vizStore.closeFilterEditing()}
115
- >
116
- <header className="text-lg font-semibold py-2 outline-none">
117
- {t('form.name')}
118
- </header>
119
- <input className="border py-1 px-4 bg-white text-gray-800" readOnly value={uncontrolledField.name}/>
120
- <header className="text-lg font-semibold py-2 outline-none">
121
- {t('form.rule')}
122
- </header>
123
- <Form
124
- field={uncontrolledField}
125
- onChange={handleChange}
126
- />
127
- <div className="flex justify-center text-green-500 mt-4">
128
- <CheckCircleIcon
129
- width="3em"
130
- height="3em"
131
- role="button"
132
- tabIndex={0}
133
- aria-label="ok"
134
- className="cursor-pointer hover:bg-green-50 p-1"
135
- onClick={handleSubmit}
136
- strokeWidth="1.5"
137
- />
84
+ <Modal show={Boolean(uncontrolledField)} title={t("editing")} onClose={() => vizStore.closeFilterEditing()}>
85
+ <div className="p-4">
86
+ <h2 className="text-base font-semibold py-2 outline-none">{t("form.name")}</h2>
87
+ <span className="inline-flex items-center rounded-full bg-indigo-100 px-3 py-0.5 text-sm font-medium text-indigo-800">
88
+ {uncontrolledField.name}
89
+ </span>
90
+ <h3 className="text-base font-semibold py-2 outline-none">{t("form.rule")}</h3>
91
+ <Form field={uncontrolledField} onChange={handleChange} />
92
+ <div className="mt-4">
93
+ <PrimaryButton
94
+ onClick={handleSubmit}
95
+ text={t("btn.confirm")}
96
+ />
97
+ <DefaultButton
98
+ className="ml-2"
99
+ onClick={() => vizStore.closeFilterEditing()}
100
+ text={t("btn.cancel")}
101
+ />
102
+ </div>
138
103
  </div>
139
104
  </Modal>
140
105
  ) : null;
141
106
  });
142
107
 
143
-
144
108
  export default FilterEditDialog;
@@ -118,7 +118,6 @@ const Slider: React.FC<SliderProps> = React.memo(function Slider ({
118
118
  };
119
119
 
120
120
  const dragHandler = fromEvent(document.body, 'mousemove').pipe(
121
- throttleTime(100),
122
121
  map(ev => {
123
122
  if (!trackRef.current || !dragging) {
124
123
  return null;
@@ -142,6 +141,7 @@ const Slider: React.FC<SliderProps> = React.memo(function Slider ({
142
141
 
143
142
  return pos;
144
143
  }),
144
+ throttleTime(100),
145
145
  filter(pos => {
146
146
  return pos !== null && pos !== range[dragging === 'left' ? 0 : 1];
147
147
  }),
package/src/index.css CHANGED
@@ -10,11 +10,11 @@ html{
10
10
  }
11
11
  }
12
12
  body {
13
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
13
+ /* font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
14
14
  'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
15
- sans-serif;
16
- -webkit-font-smoothing: antialiased;
17
- -moz-osx-font-smoothing: grayscale;
15
+ sans-serif; */
16
+ /* -webkit-font-smoothing: antialiased;
17
+ -moz-osx-font-smoothing: grayscale; */
18
18
  margin: 0px;
19
19
  padding: 0px;
20
20
  }
package/src/index.tsx CHANGED
@@ -1,22 +1,22 @@
1
- import React, { createContext, useEffect, useRef, useState } from 'react';
2
- import { StyleSheetManager } from 'styled-components';
3
- import root from 'react-shadow';
4
- import { DOM } from '@kanaries/react-beautiful-dnd';
5
- import { observer } from 'mobx-react-lite';
6
- import App, { IGWProps } from './App';
7
- import { StoreWrapper } from './store/index';
8
- import { FieldsContextWrapper } from './fields/fieldsContext';
1
+ import React, { createContext, useEffect, useRef, useState } from "react";
2
+ import { StyleSheetManager } from "styled-components";
3
+ import root from "react-shadow";
4
+ import { DOM } from "@kanaries/react-beautiful-dnd";
5
+ import { observer } from "mobx-react-lite";
6
+ import App, { IGWProps } from "./App";
7
+ import { StoreWrapper } from "./store/index";
8
+ import { FieldsContextWrapper } from "./fields/fieldsContext";
9
9
 
10
- import './empty_sheet.css';
10
+ import "./empty_sheet.css";
11
11
  import tailwindStyle from "tailwindcss/tailwind.css?inline";
12
- import style from './index.css?inline';
13
-
12
+ import style from "./index.css?inline";
14
13
 
15
14
  export const ShadowDomContext = createContext<{ root: ShadowRoot | null }>({ root: null });
16
15
 
17
- export const GraphicWalker: React.FC<IGWProps> = observer(props => {
16
+ export const GraphicWalker: React.FC<IGWProps> = observer((props) => {
18
17
  const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null);
19
18
  const rootRef = useRef<HTMLDivElement>(null);
19
+ const { storeRef } = props;
20
20
 
21
21
  useEffect(() => {
22
22
  if (rootRef.current) {
@@ -32,20 +32,20 @@ export const GraphicWalker: React.FC<IGWProps> = observer(props => {
32
32
  }, []);
33
33
 
34
34
  return (
35
- <root.div mode="open" ref={rootRef}>
36
- <style>{tailwindStyle}</style>
37
- <style>{style}</style>
38
- {shadowRoot && (
39
- <StyleSheetManager target={shadowRoot}>
40
- <StoreWrapper keepAlive={props.keepAlive}>
35
+ <StoreWrapper keepAlive={props.keepAlive} storeRef={storeRef}>
36
+ <root.div mode="open" ref={rootRef}>
37
+ <style>{tailwindStyle}</style>
38
+ <style>{style}</style>
39
+ {shadowRoot && (
40
+ <StyleSheetManager target={shadowRoot}>
41
41
  <FieldsContextWrapper>
42
42
  <ShadowDomContext.Provider value={{ root: shadowRoot }}>
43
43
  <App {...props} />
44
44
  </ShadowDomContext.Provider>
45
45
  </FieldsContextWrapper>
46
- </StoreWrapper>
47
- </StyleSheetManager>
48
- )}
49
- </root.div>
46
+ </StyleSheetManager>
47
+ )}
48
+ </root.div>
49
+ </StoreWrapper>
50
50
  );
51
51
  });
@@ -9,6 +9,8 @@ import { baseVis, IReasonType } from "./std2vegaSpec";
9
9
  import RadioGroupButtons from "./radioGroupButtons";
10
10
  import { formatFieldName, mergeMeasures } from "./utils";
11
11
  import { useTranslation } from "react-i18next";
12
+ import { useCurrentMediaTheme } from "../utils/media";
13
+ import { builtInThemes } from "../vis/theme";
12
14
 
13
15
  const collection = Insight.IntentionWorkerCollection.init();
14
16
 
@@ -41,6 +43,8 @@ const InsightMainBoard: React.FC<InsightMainBoardProps> = (props) => {
41
43
  const [valueExp, setValueExp] = useState<IMeasureWithStat[]>([]);
42
44
  const { t } = useTranslation();
43
45
  const container = useRef<HTMLDivElement>(null);
46
+ const mediaTheme = useCurrentMediaTheme();
47
+ const themeConfig = builtInThemes['g2'][mediaTheme];
44
48
 
45
49
  const dimsWithTypes = useMemo(() => {
46
50
  const dimensions = fields
@@ -111,10 +115,13 @@ const InsightMainBoard: React.FC<InsightMainBoardProps> = (props) => {
111
115
  true
112
116
  );
113
117
  if (container.current) {
114
- embed(container.current, _vegaSpec);
118
+ embed(container.current, _vegaSpec, {
119
+ actions: false,
120
+ config: themeConfig
121
+ });
115
122
  }
116
123
  }
117
- }, [visIndex, recSpaces, visSpaces, fields, dataSource]);
124
+ }, [visIndex, recSpaces, visSpaces, fields, dataSource, themeConfig]);
118
125
 
119
126
  const FilterDesc = useMemo<React.ReactElement[]>(() => {
120
127
  if (filters) {
package/src/interfaces.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { StatFuncName } from "visual-insights/build/esm/statistics";
2
2
  import { AggFC } from 'cube-core/built/types';
3
- import { IAnalyticType, IMutField as VIMutField, ISemanticType } from 'visual-insights';
3
+ import { IAnalyticType, ISemanticType } from 'visual-insights';
4
4
 
5
5
  export type DeepReadonly<T extends Record<keyof any, any>> = {
6
6
  readonly [K in keyof T]: T[K] extends Record<keyof any, any> ? DeepReadonly<T[K]> : T[K];
@@ -36,6 +36,28 @@ export interface IUncertainMutField {
36
36
  analyticType: IAnalyticType | '?';
37
37
  }
38
38
 
39
+
40
+ export type IExpParamter = {
41
+ type: 'field';
42
+ value: string;
43
+ } | {
44
+ type: 'value';
45
+ value: any;
46
+ } | {
47
+ type: 'expression';
48
+ value: IExpression;
49
+ } | {
50
+ type: 'constant';
51
+ value: any;
52
+ }
53
+
54
+
55
+ export interface IExpression {
56
+ op: 'bin' | 'log2' | 'log10' | 'one' | 'binCount';
57
+ params: IExpParamter[];
58
+ as: string;
59
+ }
60
+
39
61
  export interface IField {
40
62
  /**
41
63
  * fid: key in data record
@@ -52,6 +74,8 @@ export interface IField {
52
74
  semanticType: ISemanticType;
53
75
  analyticType: IAnalyticType;
54
76
  cmp?: (a: any, b: any) => number;
77
+ computed?: boolean;
78
+ expressoion?: IExpression;
55
79
  }
56
80
 
57
81
  export interface IViewField extends IField {
@@ -176,7 +200,7 @@ export interface IVisualConfig {
176
200
 
177
201
  export interface IVisSpec {
178
202
  readonly visId: string;
179
- readonly name?: [string, Record<string, any>?];
203
+ readonly name?: string;
180
204
  readonly encodings: DeepReadonly<DraggableFieldState>;
181
205
  readonly config: DeepReadonly<IVisualConfig>;
182
206
  }
@@ -184,4 +208,7 @@ export interface IVisSpec {
184
208
  export enum ISegmentKey {
185
209
  vis = 'vis',
186
210
  data = 'data'
187
- }
211
+ }
212
+
213
+ export type IThemeKey = 'vega' | 'g2';
214
+ export type IDarkMode = 'media' | 'light' | 'dark';