@kanaries/graphic-walker 0.2.12 → 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 (99) 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/dataTable/index.d.ts +10 -0
  7. package/dist/components/dataTable/pagination.d.ts +10 -0
  8. package/dist/components/dropdownContext/index.d.ts +13 -0
  9. package/dist/components/dropdownSelect/index.d.ts +17 -0
  10. package/dist/components/modal.d.ts +1 -0
  11. package/dist/components/tabs/defaultTab.d.ts +14 -0
  12. package/dist/components/tabs/{pureTab.d.ts → editableTab.d.ts} +2 -2
  13. package/dist/components/toolbar/toolbar-item.d.ts +1 -0
  14. package/dist/dataSource/dataSelection/config.d.ts +2 -0
  15. package/dist/dataSource/datasetConfig/index.d.ts +3 -0
  16. package/dist/dataSource/index.d.ts +1 -1
  17. package/dist/fields/datasetFields/dimFields.d.ts +2 -2
  18. package/dist/fields/datasetFields/meaFields.d.ts +2 -2
  19. package/dist/fields/encodeFields/singleEncodeDropDown.d.ts +17 -0
  20. package/dist/fields/encodeFields/singleEncodeEditor.d.ts +11 -0
  21. package/dist/fields/obComponents/obPill.d.ts +3 -3
  22. package/dist/graphic-walker.es.js +21038 -19133
  23. package/dist/graphic-walker.es.js.map +1 -1
  24. package/dist/graphic-walker.umd.js +247 -170
  25. package/dist/graphic-walker.umd.js.map +1 -1
  26. package/dist/insightBoard/index.d.ts +1 -1
  27. package/dist/interfaces.d.ts +5 -0
  28. package/dist/renderer/index.d.ts +3 -1
  29. package/dist/segments/segmentNav.d.ts +3 -0
  30. package/dist/store/commonStore.d.ts +7 -1
  31. package/dist/store/visualSpecStore.d.ts +1 -0
  32. package/dist/utils/index.d.ts +2 -0
  33. package/dist/utils/media.d.ts +2 -0
  34. package/dist/vis/react-vega.d.ts +2 -0
  35. package/dist/vis/theme.d.ts +130 -0
  36. package/package.json +2 -1
  37. package/src/App.tsx +74 -46
  38. package/src/components/button/base.ts +1 -0
  39. package/src/components/button/default.tsx +6 -2
  40. package/src/components/button/defaultMini.tsx +17 -0
  41. package/src/components/button/primary.tsx +6 -2
  42. package/src/components/button/primaryMini.tsx +21 -0
  43. package/src/components/callout.tsx +4 -1
  44. package/src/components/clickMenu.tsx +4 -2
  45. package/src/components/container.tsx +9 -0
  46. package/src/components/dataTable/index.tsx +177 -0
  47. package/src/components/dataTable/pagination.tsx +44 -0
  48. package/src/components/dataTypeIcon.tsx +1 -1
  49. package/src/components/dropdownContext/index.tsx +64 -0
  50. package/src/components/dropdownSelect/index.tsx +92 -0
  51. package/src/components/modal.tsx +26 -14
  52. package/src/components/tabs/defaultTab.tsx +43 -0
  53. package/src/components/tabs/{pureTab.tsx → editableTab.tsx} +7 -7
  54. package/src/components/toolbar/components.tsx +18 -1
  55. package/src/components/toolbar/index.tsx +5 -0
  56. package/src/components/toolbar/toolbar-button.tsx +6 -1
  57. package/src/components/toolbar/toolbar-item.tsx +4 -0
  58. package/src/components/toolbar/toolbar-select-button.tsx +21 -4
  59. package/src/components/toolbar/toolbar-toggle-button.tsx +6 -1
  60. package/src/components/tooltip.tsx +4 -1
  61. package/src/dataSource/dataSelection/config.ts +28 -0
  62. package/src/dataSource/dataSelection/csvData.tsx +77 -32
  63. package/src/dataSource/dataSelection/gwFile.tsx +0 -8
  64. package/src/dataSource/dataSelection/index.tsx +1 -2
  65. package/src/dataSource/dataSelection/publicData.tsx +2 -3
  66. package/src/dataSource/datasetConfig/index.tsx +21 -0
  67. package/src/dataSource/index.tsx +81 -61
  68. package/src/dataSource/table.tsx +11 -155
  69. package/src/fields/aestheticFields.tsx +3 -1
  70. package/src/fields/components.tsx +21 -2
  71. package/src/fields/datasetFields/dimFields.tsx +43 -35
  72. package/src/fields/datasetFields/index.tsx +2 -2
  73. package/src/fields/datasetFields/meaFields.tsx +73 -47
  74. package/src/fields/encodeFields/singleEncodeDropDown.tsx +92 -0
  75. package/src/fields/encodeFields/singleEncodeEditor.tsx +78 -0
  76. package/src/fields/filterField/filterEditDialog.tsx +2 -1
  77. package/src/fields/filterField/filterPill.tsx +1 -1
  78. package/src/fields/filterField/slider.tsx +1 -1
  79. package/src/fields/filterField/tabs.tsx +11 -21
  80. package/src/fields/obComponents/obPill.tsx +65 -35
  81. package/src/index.css +13 -0
  82. package/src/insightBoard/index.tsx +24 -23
  83. package/src/insightBoard/radioGroupButtons.tsx +7 -0
  84. package/src/interfaces.ts +6 -0
  85. package/src/lib/inferMeta.ts +1 -1
  86. package/src/locales/en-US.json +14 -3
  87. package/src/locales/zh-CN.json +12 -1
  88. package/src/main.tsx +1 -1
  89. package/src/renderer/index.tsx +3 -1
  90. package/src/segments/segmentNav.tsx +58 -0
  91. package/src/segments/visNav.tsx +2 -2
  92. package/src/store/commonStore.ts +28 -2
  93. package/src/store/visualSpecStore.ts +16 -0
  94. package/src/utils/index.ts +19 -0
  95. package/src/utils/media.ts +26 -0
  96. package/src/utils/normalization.ts +2 -1
  97. package/src/vis/react-vega.tsx +20 -4
  98. package/src/vis/theme.ts +126 -0
  99. package/src/visualSettings/index.tsx +24 -8
@@ -1,3 +1,3 @@
1
- import React from 'react';
1
+ import React from "react";
2
2
  declare const _default: React.FunctionComponent<{}>;
3
3
  export default _default;
@@ -104,6 +104,7 @@ export interface DraggableFieldState {
104
104
  shape: IViewField[];
105
105
  theta: IViewField[];
106
106
  radius: IViewField[];
107
+ details: IViewField[];
107
108
  filters: IFilterField[];
108
109
  }
109
110
  export interface IDraggableStateKey {
@@ -149,3 +150,7 @@ export interface IVisSpec {
149
150
  readonly encodings: DeepReadonly<DraggableFieldState>;
150
151
  readonly config: DeepReadonly<IVisualConfig>;
151
152
  }
153
+ export declare enum ISegmentKey {
154
+ vis = "vis",
155
+ data = "data"
156
+ }
@@ -1,4 +1,6 @@
1
1
  import React from 'react';
2
2
  import { IReactVegaHandler } from '../vis/react-vega';
3
- declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<React.RefAttributes<IReactVegaHandler>, "key"> & React.RefAttributes<IReactVegaHandler>>>;
3
+ declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<{
4
+ themeKey?: "vega" | "g2" | undefined;
5
+ } & React.RefAttributes<IReactVegaHandler>, "key" | "themeKey"> & React.RefAttributes<IReactVegaHandler>>>;
4
6
  export default _default;
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ declare const _default: React.FunctionComponent<{}>;
3
+ export default _default;
@@ -1,4 +1,4 @@
1
- import { DataSet, Filters, IDataSet, IDataSetInfo, IDataSource, IMutField, IRow } from '../interfaces';
1
+ import { DataSet, Filters, IDataSet, IDataSetInfo, IDataSource, IMutField, IRow, ISegmentKey } from '../interfaces';
2
2
  export declare class CommonStore {
3
3
  datasets: IDataSet[];
4
4
  dataSources: IDataSource[];
@@ -12,15 +12,21 @@ export declare class CommonStore {
12
12
  show: boolean;
13
13
  position: [number, number];
14
14
  };
15
+ showDataConfig: boolean;
15
16
  filters: Filters;
17
+ segmentKey: ISegmentKey;
16
18
  constructor();
17
19
  get currentDataset(): DataSet;
20
+ setSegmentKey(sk: ISegmentKey): void;
18
21
  setShowDSPanel(show: boolean): void;
22
+ setShowDataConfig(show: boolean): void;
19
23
  setShowInsightBoard(show: boolean): void;
20
24
  showEmbededMenu(position: [number, number]): void;
21
25
  closeEmbededMenu(): void;
22
26
  initTempDS(): void;
23
27
  updateTempFields(fields: IMutField[]): void;
28
+ updateCurrentDatasetMetas(fid: string, diffMeta: Partial<IMutField>): void;
29
+ updateTempDatasetMetas(fid: string, diffMeta: Partial<IMutField>): void;
24
30
  updateTempFieldAnalyticType(fieldKey: string, analyticType: IMutField['analyticType']): void;
25
31
  updateTempFieldSemanticType(fieldKey: string, semanticType: IMutField['semanticType']): void;
26
32
  updateTempName(name: string): void;
@@ -93,6 +93,7 @@ export declare class VizSpecStore {
93
93
  reorderField(stateKey: keyof DraggableFieldState, sourceIndex: number, destinationIndex: number): void;
94
94
  moveField(sourceKey: keyof DraggableFieldState, sourceIndex: number, destinationKey: keyof DraggableFieldState, destinationIndex: number): void;
95
95
  removeField(sourceKey: keyof DraggableFieldState, sourceIndex: number): void;
96
+ replaceField(sourceKey: keyof DraggableFieldState, sourceIndex: number, fid: string): void;
96
97
  private appendFilter;
97
98
  writeFilter(index: number, rule: IFilterRule | null): void;
98
99
  setFilterEditing(index: number): void;
@@ -20,3 +20,5 @@ export declare function extendCountField(dataSource: IRow[], fields: IMutField[]
20
20
  dataSource: IRow[];
21
21
  fields: IMutField[];
22
22
  };
23
+ export declare function getRange(nums: number[]): [number, number];
24
+ export declare function makeNumbersBeautiful(nums: number[]): number[];
@@ -0,0 +1,2 @@
1
+ export declare function currentMediaTheme(): "dark" | "light";
2
+ export declare function useCurrentMediaTheme(): "dark" | "light";
@@ -27,6 +27,8 @@ interface ReactVegaProps {
27
27
  onGeomClick?: (values: any, e: any) => void;
28
28
  selectEncoding: SingleViewProps['selectEncoding'];
29
29
  brushEncoding: SingleViewProps['brushEncoding'];
30
+ /** @default "vega" */
31
+ themeKey?: 'vega' | 'g2';
30
32
  }
31
33
  interface SingleViewProps {
32
34
  x: IViewField;
@@ -0,0 +1,130 @@
1
+ export declare const VegaTheme: {
2
+ readonly light: {
3
+ readonly background: "transparent";
4
+ };
5
+ readonly dark: {
6
+ readonly background: "transparent";
7
+ readonly axis: {
8
+ readonly gridColor: "#666";
9
+ readonly domainColor: "#d1d5db";
10
+ readonly tickColor: "#d1d5db";
11
+ readonly labelColor: "#d1d5db";
12
+ };
13
+ readonly legend: {
14
+ readonly labelColor: "#d1d5db";
15
+ readonly titleColor: "#d1d5db";
16
+ };
17
+ };
18
+ };
19
+ export declare const AntVTheme: {
20
+ readonly light: {
21
+ readonly area: {
22
+ readonly fill: "#5B8FF9";
23
+ };
24
+ readonly bar: {
25
+ readonly fill: "#5B8FF9";
26
+ };
27
+ readonly circle: {
28
+ readonly fill: "#5B8FF9";
29
+ };
30
+ readonly line: {
31
+ readonly stroke: "#5B8FF9";
32
+ };
33
+ readonly point: {
34
+ readonly stroke: "#5B8FF9";
35
+ };
36
+ readonly rect: {
37
+ readonly fill: "#5B8FF9";
38
+ };
39
+ readonly tick: {
40
+ readonly stroke: "#5B8FF9";
41
+ };
42
+ readonly boxplot: {
43
+ readonly fill: "#5B8FF9";
44
+ };
45
+ readonly errorbar: {
46
+ readonly stroke: "#5B8FF9";
47
+ };
48
+ readonly errorband: {
49
+ readonly fill: "#5B8FF9";
50
+ };
51
+ readonly arc: {
52
+ readonly fill: "#5B8FF9";
53
+ };
54
+ readonly background: "transparent";
55
+ readonly range: {
56
+ readonly category: readonly ["#5B8FF9", "#61DDAA", "#65789B", "#F6BD16", "#7262FD", "#78D3F8", "#9661BC", "#F6903D", "#008685", "#F08BB4"];
57
+ readonly diverging: readonly ["#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"];
58
+ readonly heatmap: readonly ["#000000", "#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"];
59
+ readonly ramp: readonly ["#EBCCFF", "#CCB0FF", "#AE95FF", "#907BFF", "#7262FD", "#5349E0", "#2F32C3", "#001BA7", "#00068C"];
60
+ };
61
+ readonly scale: {
62
+ readonly continuous: {
63
+ readonly range: readonly ["#f7fbff", "#08306b"];
64
+ };
65
+ };
66
+ };
67
+ readonly dark: {
68
+ readonly area: {
69
+ readonly fill: "#5B8FF9";
70
+ };
71
+ readonly bar: {
72
+ readonly fill: "#5B8FF9";
73
+ };
74
+ readonly circle: {
75
+ readonly fill: "#5B8FF9";
76
+ };
77
+ readonly line: {
78
+ readonly stroke: "#5B8FF9";
79
+ };
80
+ readonly point: {
81
+ readonly stroke: "#5B8FF9";
82
+ };
83
+ readonly rect: {
84
+ readonly fill: "#5B8FF9";
85
+ };
86
+ readonly tick: {
87
+ readonly stroke: "#5B8FF9";
88
+ };
89
+ readonly boxplot: {
90
+ readonly fill: "#5B8FF9";
91
+ };
92
+ readonly errorbar: {
93
+ readonly stroke: "#5B8FF9";
94
+ };
95
+ readonly errorband: {
96
+ readonly fill: "#5B8FF9";
97
+ };
98
+ readonly arc: {
99
+ readonly fill: "#5B8FF9";
100
+ };
101
+ readonly background: "transparent";
102
+ readonly axis: {
103
+ readonly gridColor: "#666";
104
+ readonly domainColor: "#d1d5db";
105
+ readonly tickColor: "#d1d5db";
106
+ readonly labelColor: "#d1d5db";
107
+ };
108
+ readonly legend: {
109
+ readonly labelColor: "#d1d5db";
110
+ readonly titleColor: "#d1d5db";
111
+ };
112
+ readonly range: {
113
+ readonly category: readonly ["#5B8FF9", "#61DDAA", "#65789B", "#F6BD16", "#7262FD", "#78D3F8", "#9661BC", "#F6903D", "#008685", "#F08BB4"];
114
+ readonly diverging: readonly ["#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"];
115
+ readonly heatmap: readonly ["#000000", "#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"];
116
+ readonly ramp: readonly ["#EBCCFF", "#CCB0FF", "#AE95FF", "#907BFF", "#7262FD", "#5349E0", "#2F32C3", "#001BA7", "#00068C"];
117
+ };
118
+ readonly scale: {
119
+ readonly continuous: {
120
+ readonly range: readonly ["#f7fbff", "#08306b"];
121
+ };
122
+ };
123
+ };
124
+ };
125
+ export declare const builtInThemes: {
126
+ [themeKey: string]: {
127
+ light: any;
128
+ dark: any;
129
+ };
130
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanaries/graphic-walker",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "scripts": {
5
5
  "dev:front_end": "vite --host",
6
6
  "dev": "npm run dev:front_end",
@@ -32,6 +32,7 @@
32
32
  },
33
33
  "types": "./dist/index.d.ts",
34
34
  "dependencies": {
35
+ "@headlessui/react": "^1.7.12",
35
36
  "@heroicons/react": "^2.0.8",
36
37
  "@kanaries/react-beautiful-dnd": "0.0.1",
37
38
  "@kanaries/web-data-loader": "0.1.5",
package/src/App.tsx CHANGED
@@ -4,7 +4,7 @@ import { observer } from "mobx-react-lite";
4
4
  import { LightBulbIcon } from "@heroicons/react/24/outline";
5
5
  import { toJS } from "mobx";
6
6
  import { useTranslation } from "react-i18next";
7
- import { IMutField, IRow } from "./interfaces";
7
+ import { IMutField, IRow, ISegmentKey } from "./interfaces";
8
8
  import type { IReactVegaHandler } from "./vis/react-vega";
9
9
  import VisualSettings from "./visualSettings";
10
10
  import { Container, NestContainer } from "./components/container";
@@ -21,6 +21,8 @@ import VisNav from "./segments/visNav";
21
21
  import { mergeLocaleRes, setLocaleLanguage } from "./locales/i18n";
22
22
  import FilterField from "./fields/filterField";
23
23
  import { guardDataKeys } from "./utils/dataPrep";
24
+ import SegmentNav from "./segments/segmentNav";
25
+ import DatasetConfig from "./dataSource/datasetConfig";
24
26
 
25
27
  export interface IGWProps {
26
28
  dataSource?: IRow[];
@@ -34,14 +36,25 @@ export interface IGWProps {
34
36
  * auto parse field key into a safe string. default is true
35
37
  */
36
38
  fieldKeyGuard?: boolean;
39
+ /** @default "vega" */
40
+ themeKey?: 'vega' | 'g2';
37
41
  }
38
42
 
39
- const App: React.FC<IGWProps> = (props) => {
40
- const { dataSource = [], rawFields = [], spec, i18nLang = "en-US", i18nResources, hideDataSourceConfig, fieldKeyGuard = true } = props;
43
+ const App = observer<IGWProps>(function App (props) {
44
+ const {
45
+ dataSource = [],
46
+ rawFields = [],
47
+ spec,
48
+ i18nLang = "en-US",
49
+ i18nResources,
50
+ hideDataSourceConfig,
51
+ fieldKeyGuard = true,
52
+ themeKey = 'vega',
53
+ } = props;
41
54
  const { commonStore, vizStore } = useGlobalStore();
42
55
  const [insightReady, setInsightReady] = useState<boolean>(true);
43
56
 
44
- const { currentDataset, datasets, vizEmbededMenu } = commonStore;
57
+ const { currentDataset, datasets, vizEmbededMenu, segmentKey } = commonStore;
45
58
 
46
59
  const { t, i18n } = useTranslation();
47
60
  const curLang = i18n.language;
@@ -107,58 +120,73 @@ const App: React.FC<IGWProps> = (props) => {
107
120
  const rendererRef = useRef<IReactVegaHandler>(null);
108
121
 
109
122
  return (
110
- <div className="App">
123
+ <div className="App font-sans dark:bg-zinc-900 dark:text-white m-0 p-0">
111
124
  {/* <div className="grow-0">
112
125
  <PageNav />
113
126
  </div> */}
114
127
  <div className="">
115
128
  {!hideDataSourceConfig && <DataSourceSegment preWorkDone={insightReady} />}
116
129
  <div className="px-2 mx-2">
117
- <VisNav />
130
+ <SegmentNav />
131
+ {
132
+ segmentKey === ISegmentKey.vis && <VisNav />
133
+ }
118
134
  </div>
119
- <Container style={{ marginTop: "0em", borderTop: "none" }}>
120
- <VisualSettings rendererHandler={rendererRef} />
121
- <div className="md:grid md:grid-cols-12 xl:grid-cols-6">
122
- <div className="md:col-span-3 xl:col-span-1">
123
- <DatasetFields />
124
- </div>
125
- <div className="md:col-span-2 xl:col-span-1">
126
- <FilterField />
127
- <AestheticFields />
128
- </div>
129
- <div className="md:col-span-7 xl:col-span-4">
130
- <div>
131
- <PosFields />
135
+ {segmentKey === ISegmentKey.vis && (
136
+ <Container style={{ marginTop: "0em", borderTop: "none" }}>
137
+ <VisualSettings rendererHandler={rendererRef} />
138
+ <div className="md:grid md:grid-cols-12 xl:grid-cols-6">
139
+ <div className="md:col-span-3 xl:col-span-1">
140
+ <DatasetFields />
141
+ </div>
142
+ <div className="md:col-span-2 xl:col-span-1">
143
+ <FilterField />
144
+ <AestheticFields />
145
+ </div>
146
+ <div className="md:col-span-7 xl:col-span-4">
147
+ <div>
148
+ <PosFields />
149
+ </div>
150
+ <NestContainer
151
+ style={{ minHeight: "600px", overflow: "auto" }}
152
+ onMouseLeave={() => {
153
+ vizEmbededMenu.show && commonStore.closeEmbededMenu();
154
+ }}
155
+ onClick={() => {
156
+ vizEmbededMenu.show && commonStore.closeEmbededMenu();
157
+ }}
158
+ >
159
+ {datasets.length > 0 && <ReactiveRenderer ref={rendererRef} themeKey={themeKey} />}
160
+ <InsightBoard />
161
+ {vizEmbededMenu.show && (
162
+ <ClickMenu x={vizEmbededMenu.position[0]} y={vizEmbededMenu.position[1]}>
163
+ <div
164
+ className="flex items-center whitespace-nowrap py-1 px-4 hover:bg-gray-100"
165
+ onClick={() => {
166
+ commonStore.closeEmbededMenu();
167
+ commonStore.setShowInsightBoard(true);
168
+ }}
169
+ >
170
+ <span className="flex-1 pr-2">
171
+ {t("App.labels.data_interpretation")}
172
+ </span>
173
+ <LightBulbIcon className="ml-1 w-3 flex-grow-0 flex-shrink-0" />
174
+ </div>
175
+ </ClickMenu>
176
+ )}
177
+ </NestContainer>
132
178
  </div>
133
- <NestContainer
134
- style={{ minHeight: "600px", overflow: "auto" }}
135
- onMouseLeave={() => {
136
- vizEmbededMenu.show && commonStore.closeEmbededMenu();
137
- }}
138
- >
139
- {datasets.length > 0 && <ReactiveRenderer ref={rendererRef} />}
140
- <InsightBoard />
141
- {vizEmbededMenu.show && (
142
- <ClickMenu x={vizEmbededMenu.position[0]} y={vizEmbededMenu.position[1]}>
143
- <div
144
- className="flex items-center whitespace-nowrap py-1 px-4 hover:bg-gray-100"
145
- onClick={() => {
146
- commonStore.closeEmbededMenu();
147
- commonStore.setShowInsightBoard(true);
148
- }}
149
- >
150
- <span className="flex-1 pr-2">{t("App.labels.data_interpretation")}</span>
151
- <LightBulbIcon className="ml-1 w-3 flex-grow-0 flex-shrink-0" />
152
- </div>
153
- </ClickMenu>
154
- )}
155
- </NestContainer>
156
179
  </div>
157
- </div>
158
- </Container>
180
+ </Container>
181
+ )}
182
+ {segmentKey === ISegmentKey.data && (
183
+ <Container style={{ marginTop: "0em", borderTop: "none" }}>
184
+ <DatasetConfig />
185
+ </Container>
186
+ )}
159
187
  </div>
160
188
  </div>
161
189
  );
162
- };
190
+ });
163
191
 
164
- export default observer(App);
192
+ export default App;
@@ -4,4 +4,5 @@ export interface ButtonBaseProps {
4
4
  onClick: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
5
5
  text: string;
6
6
  disabled?: boolean;
7
+ className?: string;
7
8
  }
@@ -2,10 +2,14 @@ import React from "react";
2
2
  import { ButtonBaseProps } from "./base";
3
3
 
4
4
  const DefaultButton: React.FC<ButtonBaseProps> = (props) => {
5
- const { text, onClick, disabled } = props;
5
+ const { text, onClick, disabled, className } = props;
6
+ let btnClassName = "inline-flex items-center rounded border border-gray-300 bg-white dark:bg-zinc-900 px-2.5 py-1.5 text-xs font-medium text-gray-700 dark:text-gray-200 shadow-sm hover:bg-gray-50 dark:hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-50"
7
+ if (className) {
8
+ btnClassName = btnClassName + " " + className;
9
+ }
6
10
  return (
7
11
  <button
8
- className="inline-block min-w-96 text-xs ml-2 pt-1 pb-1 pl-6 pr-6 border border-gray-500 rounded-sm hover:bg-gray-800 hover:border-gray-800 hover:text-white disabled:bg-gray-400 disabled:border-gray-400 disabled:text-white disabled:cursor-not-allowed disabled:text-white"
12
+ className={btnClassName}
9
13
  onClick={onClick}
10
14
  disabled={disabled}
11
15
  >
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { ButtonBaseProps } from "./base";
3
+
4
+ const DefaultMiniButton: React.FC<ButtonBaseProps> = (props) => {
5
+ const { text, onClick, disabled } = props;
6
+ return (
7
+ <button
8
+ className="inline-block min-w-96 text-xs ml-2 pt-1 pb-1 pl-6 pr-6 border border-gray-500 rounded-sm hover:bg-gray-800 hover:border-gray-800 hover:text-white disabled:bg-gray-400 disabled:border-gray-400 disabled:text-white disabled:cursor-not-allowed disabled:text-white"
9
+ onClick={onClick}
10
+ disabled={disabled}
11
+ >
12
+ {text}
13
+ </button>
14
+ );
15
+ };
16
+
17
+ export default DefaultMiniButton;
@@ -2,10 +2,14 @@ import React from "react";
2
2
  import { ButtonBaseProps } from "./base";
3
3
 
4
4
  const PrimaryButton: React.FC<ButtonBaseProps> = (props) => {
5
- const { text, onClick, disabled } = props;
5
+ const { text, onClick, disabled, className } = props;
6
+ let btnClassName = "inline-flex items-center rounded border border-transparent bg-indigo-600 px-2.5 py-1.5 text-xs font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
7
+ if (className) {
8
+ btnClassName = btnClassName + " " + className;
9
+ }
6
10
  return (
7
11
  <button
8
- className="inline-block min-w-96 text-xs ml-2 pt-1 pb-1 pl-6 pr-6 border border-gray-800 bg-gray-800 text-white rounded-sm hover:bg-white border-gray-800 hover:text-gray-800 cursor-pointer disabled:bg-gray-400 disabled:border-gray-400 disabled:text-white disabled:cursor-not-allowed disabled:text-white"
12
+ className={btnClassName}
9
13
  onClick={onClick}
10
14
  disabled={disabled}
11
15
  >
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { ButtonBaseProps } from "./base";
3
+
4
+ const PrimaryMiniButton: React.FC<ButtonBaseProps> = (props) => {
5
+ const { text, onClick, disabled, className } = props;
6
+ let btnClassName = "inline-block min-w-96 text-xs ml-2 pt-1 pb-1 pl-6 pr-6 border border-gray-800 bg-gray-800 text-white rounded-sm hover:bg-white dark:bg-zinc-900 border-gray-800 hover:text-gray-800 cursor-pointer disabled:bg-gray-400 disabled:border-gray-400 disabled:text-white disabled:cursor-not-allowed disabled:text-white"
7
+ if (className) {
8
+ btnClassName = btnClassName + " " + className;
9
+ }
10
+ return (
11
+ <button
12
+ className={btnClassName}
13
+ onClick={onClick}
14
+ disabled={disabled}
15
+ >
16
+ {text}
17
+ </button>
18
+ );
19
+ };
20
+
21
+ export default PrimaryMiniButton;
@@ -27,6 +27,9 @@ const Bubble = styled.div`
27
27
  transform: translate(-50%, -50%) rotate(45deg);
28
28
  background-color: #fff;
29
29
  border-radius: 1px;
30
+ @media (prefers-color-scheme: dark) {
31
+ background-color: #000;
32
+ }
30
33
  }
31
34
  `;
32
35
 
@@ -49,7 +52,7 @@ const Callout = memo<CalloutProps>(function Callout({ target, children }) {
49
52
  root &&
50
53
  pos &&
51
54
  createPortal(
52
- <Bubble role="dialog" className="fixed bg-white z-50" style={{ left: pos[0], top: pos[1] + 4 }}>
55
+ <Bubble role="dialog" className="fixed bg-white dark:bg-zinc-900 z-50" style={{ left: pos[0], top: pos[1] + 4 }}>
53
56
  {children}
54
57
  </Bubble>,
55
58
  root
@@ -8,9 +8,11 @@ const MenuContainer = styled.div`
8
8
  position: absolute;
9
9
  z-index: 99;
10
10
  cursor: pointer;
11
- /* box-shadow: 0px 0px 8px 1px rgba(0, 0, 0, 0.09); */
12
- /* border-radius: 2px; */
13
11
  padding: 4px;
12
+ @media (prefers-color-scheme: dark) {
13
+ background-color: #000;
14
+ border: 1px solid #4b5563;
15
+ }
14
16
  `;
15
17
  interface ClickMenuProps {
16
18
  x: number;
@@ -5,6 +5,11 @@ export const Container = styled.div`
5
5
  padding: 1em;
6
6
  margin: 1em;
7
7
  background-color: #fff;
8
+ // dark theme
9
+ @media (prefers-color-scheme: dark) {
10
+ background-color: #000;
11
+ border: 1px solid #4b5563;
12
+ }
8
13
  `;
9
14
 
10
15
  export const NestContainer = styled.div`
@@ -13,4 +18,8 @@ export const NestContainer = styled.div`
13
18
  font-size: 12px;
14
19
  margin: 0.2em;
15
20
  background-color: #fff;
21
+ @media (prefers-color-scheme: dark) {
22
+ background-color: #000;
23
+ border: 1px solid #4b5563;
24
+ }
16
25
  `;