@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.
Files changed (99) hide show
  1. package/dist/App.d.ts +6 -3
  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/callout.d.ts +2 -0
  7. package/dist/components/dropdownContext/index.d.ts +13 -0
  8. package/dist/components/dropdownSelect/index.d.ts +17 -0
  9. package/dist/components/modal.d.ts +1 -0
  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 +4 -0
  13. package/dist/components/tooltip.d.ts +2 -0
  14. package/dist/dataSource/dataSelection/config.d.ts +2 -0
  15. package/dist/dataSource/index.d.ts +1 -1
  16. package/dist/fields/components.d.ts +0 -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/filterField/filterEditDialog.d.ts +1 -1
  22. package/dist/fields/obComponents/obPill.d.ts +3 -3
  23. package/dist/graphic-walker.es.js +21205 -19397
  24. package/dist/graphic-walker.es.js.map +1 -1
  25. package/dist/graphic-walker.umd.js +181 -236
  26. package/dist/graphic-walker.umd.js.map +1 -1
  27. package/dist/insightBoard/index.d.ts +1 -1
  28. package/dist/interfaces.d.ts +3 -0
  29. package/dist/renderer/index.d.ts +7 -3
  30. package/dist/store/visualSpecStore.d.ts +1 -0
  31. package/dist/utils/index.d.ts +2 -0
  32. package/dist/utils/media.d.ts +3 -0
  33. package/dist/vis/react-vega.d.ts +5 -1
  34. package/dist/vis/theme.d.ts +146 -0
  35. package/dist/visualSettings/index.d.ts +2 -1
  36. package/package.json +2 -1
  37. package/src/App.tsx +24 -16
  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 +9 -4
  44. package/src/components/clickMenu.tsx +1 -5
  45. package/src/components/dataTable/index.tsx +42 -52
  46. package/src/components/dataTable/pagination.tsx +4 -4
  47. package/src/components/dataTypeIcon.tsx +1 -1
  48. package/src/components/dropdownContext/index.tsx +64 -0
  49. package/src/components/dropdownSelect/index.tsx +92 -0
  50. package/src/components/modal.tsx +20 -22
  51. package/src/components/sizeSetting.tsx +2 -2
  52. package/src/components/tabs/defaultTab.tsx +4 -4
  53. package/src/components/tabs/editableTab.tsx +5 -5
  54. package/src/components/toolbar/components.tsx +10 -8
  55. package/src/components/toolbar/index.tsx +16 -4
  56. package/src/components/toolbar/toolbar-button.tsx +8 -2
  57. package/src/components/toolbar/toolbar-item.tsx +18 -9
  58. package/src/components/toolbar/toolbar-select-button.tsx +21 -8
  59. package/src/components/toolbar/toolbar-toggle-button.tsx +8 -2
  60. package/src/components/tooltip.tsx +10 -3
  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/index.tsx +80 -61
  67. package/src/fields/aestheticFields.tsx +3 -1
  68. package/src/fields/components.tsx +20 -38
  69. package/src/fields/datasetFields/dimFields.tsx +43 -35
  70. package/src/fields/datasetFields/index.tsx +3 -4
  71. package/src/fields/datasetFields/meaFields.tsx +73 -47
  72. package/src/fields/encodeFields/singleEncodeDropDown.tsx +92 -0
  73. package/src/fields/encodeFields/singleEncodeEditor.tsx +78 -0
  74. package/src/fields/filterField/filterEditDialog.tsx +63 -98
  75. package/src/fields/filterField/filterPill.tsx +1 -1
  76. package/src/fields/filterField/slider.tsx +2 -2
  77. package/src/fields/filterField/tabs.tsx +11 -21
  78. package/src/fields/obComponents/obPill.tsx +65 -35
  79. package/src/index.css +13 -0
  80. package/src/insightBoard/index.tsx +24 -23
  81. package/src/insightBoard/mainBoard.tsx +9 -2
  82. package/src/insightBoard/radioGroupButtons.tsx +7 -0
  83. package/src/interfaces.ts +5 -1
  84. package/src/lib/inferMeta.ts +1 -1
  85. package/src/locales/en-US.json +11 -5
  86. package/src/locales/i18n.ts +7 -0
  87. package/src/locales/ja-JP.json +195 -0
  88. package/src/locales/zh-CN.json +9 -3
  89. package/src/main.tsx +1 -1
  90. package/src/renderer/index.tsx +96 -70
  91. package/src/store/visualSpecStore.ts +16 -0
  92. package/src/utils/index.ts +19 -0
  93. package/src/utils/media.ts +31 -0
  94. package/src/utils/normalization.ts +2 -1
  95. package/src/vis/react-vega.tsx +36 -5
  96. package/src/vis/theme.ts +124 -0
  97. package/src/visualSettings/index.tsx +29 -33
  98. package/dist/components/container.d.ts +0 -2
  99. package/src/components/container.tsx +0 -16
@@ -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 {
@@ -153,3 +154,5 @@ export declare enum ISegmentKey {
153
154
  vis = "vis",
154
155
  data = "data"
155
156
  }
157
+ export type IThemeKey = 'vega' | 'g2';
158
+ export type IDarkMode = 'media' | 'light' | 'dark';
@@ -1,4 +1,8 @@
1
- import React from 'react';
2
- import { IReactVegaHandler } from '../vis/react-vega';
3
- declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<React.RefAttributes<IReactVegaHandler>, "key"> & React.RefAttributes<IReactVegaHandler>>>;
1
+ import React from "react";
2
+ import { IReactVegaHandler } from "../vis/react-vega";
3
+ import { IDarkMode, IThemeKey } from "../interfaces";
4
+ declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<{
5
+ themeKey?: IThemeKey | undefined;
6
+ dark?: IDarkMode | undefined;
7
+ } & React.RefAttributes<IReactVegaHandler>, "dark" | "key" | "themeKey"> & React.RefAttributes<IReactVegaHandler>>>;
4
8
  export default _default;
@@ -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,3 @@
1
+ import { IDarkMode } from "../interfaces";
2
+ export declare function currentMediaTheme(): "dark" | "light";
3
+ export declare function useCurrentMediaTheme(mode?: IDarkMode | undefined): "dark" | "light";
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { IViewField, IRow, IStackMode } from '../interfaces';
2
+ import { IViewField, IRow, IStackMode, IDarkMode, IThemeKey } from '../interfaces';
3
3
  export interface IReactVegaHandler {
4
4
  getSVGData: () => Promise<string[]>;
5
5
  getCanvasData: () => Promise<string[]>;
@@ -27,6 +27,9 @@ 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?: IThemeKey;
32
+ dark?: IDarkMode;
30
33
  }
31
34
  interface SingleViewProps {
32
35
  x: IViewField;
@@ -48,6 +51,7 @@ interface SingleViewProps {
48
51
  asCrossFilterTrigger: boolean;
49
52
  selectEncoding: 'default' | 'none';
50
53
  brushEncoding: 'x' | 'y' | 'default' | 'none';
54
+ hideLegend?: boolean;
51
55
  }
52
56
  declare const ReactVega: React.ForwardRefExoticComponent<ReactVegaProps & React.RefAttributes<IReactVegaHandler>>;
53
57
  export default ReactVega;
@@ -0,0 +1,146 @@
1
+ export declare const VegaTheme: {
2
+ readonly light: {
3
+ readonly background: "transparent";
4
+ };
5
+ readonly dark: {
6
+ background: string;
7
+ header: {
8
+ titleColor: string;
9
+ labelColor: string;
10
+ };
11
+ axis: {
12
+ gridColor: string;
13
+ domainColor: string;
14
+ tickColor: string;
15
+ labelColor: string;
16
+ titleColor: string;
17
+ };
18
+ legend: {
19
+ labelColor: string;
20
+ titleColor: string;
21
+ };
22
+ view: {
23
+ stroke: string;
24
+ };
25
+ };
26
+ };
27
+ export declare const AntVTheme: {
28
+ readonly light: {
29
+ readonly area: {
30
+ readonly fill: "#5B8FF9";
31
+ };
32
+ readonly bar: {
33
+ readonly fill: "#5B8FF9";
34
+ };
35
+ readonly circle: {
36
+ readonly fill: "#5B8FF9";
37
+ };
38
+ readonly line: {
39
+ readonly stroke: "#5B8FF9";
40
+ };
41
+ readonly point: {
42
+ readonly stroke: "#5B8FF9";
43
+ };
44
+ readonly rect: {
45
+ readonly fill: "#5B8FF9";
46
+ };
47
+ readonly tick: {
48
+ readonly stroke: "#5B8FF9";
49
+ };
50
+ readonly boxplot: {
51
+ readonly fill: "#5B8FF9";
52
+ };
53
+ readonly errorbar: {
54
+ readonly stroke: "#5B8FF9";
55
+ };
56
+ readonly errorband: {
57
+ readonly fill: "#5B8FF9";
58
+ };
59
+ readonly arc: {
60
+ readonly fill: "#5B8FF9";
61
+ };
62
+ readonly background: "transparent";
63
+ readonly range: {
64
+ readonly category: readonly ["#5B8FF9", "#61DDAA", "#65789B", "#F6BD16", "#7262FD", "#78D3F8", "#9661BC", "#F6903D", "#008685", "#F08BB4"];
65
+ readonly diverging: readonly ["#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"];
66
+ readonly heatmap: readonly ["#000000", "#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"];
67
+ readonly ramp: readonly ["#EBCCFF", "#CCB0FF", "#AE95FF", "#907BFF", "#7262FD", "#5349E0", "#2F32C3", "#001BA7", "#00068C"];
68
+ };
69
+ readonly scale: {
70
+ readonly continuous: {
71
+ readonly range: readonly ["#f7fbff", "#08306b"];
72
+ };
73
+ };
74
+ };
75
+ readonly dark: {
76
+ readonly area: {
77
+ readonly fill: "#5B8FF9";
78
+ };
79
+ readonly bar: {
80
+ readonly fill: "#5B8FF9";
81
+ };
82
+ readonly circle: {
83
+ readonly fill: "#5B8FF9";
84
+ };
85
+ readonly line: {
86
+ readonly stroke: "#5B8FF9";
87
+ };
88
+ readonly point: {
89
+ readonly stroke: "#5B8FF9";
90
+ };
91
+ readonly rect: {
92
+ readonly fill: "#5B8FF9";
93
+ };
94
+ readonly tick: {
95
+ readonly stroke: "#5B8FF9";
96
+ };
97
+ readonly boxplot: {
98
+ readonly fill: "#5B8FF9";
99
+ };
100
+ readonly errorbar: {
101
+ readonly stroke: "#5B8FF9";
102
+ };
103
+ readonly errorband: {
104
+ readonly fill: "#5B8FF9";
105
+ };
106
+ readonly arc: {
107
+ readonly fill: "#5B8FF9";
108
+ };
109
+ readonly range: {
110
+ readonly category: readonly ["#5B8FF9", "#61DDAA", "#65789B", "#F6BD16", "#7262FD", "#78D3F8", "#9661BC", "#F6903D", "#008685", "#F08BB4"];
111
+ readonly diverging: readonly ["#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"];
112
+ readonly heatmap: readonly ["#000000", "#7b3294", "#c2a5cf", "#f7f7f7", "#a6dba0", "#008837"];
113
+ readonly ramp: readonly ["#EBCCFF", "#CCB0FF", "#AE95FF", "#907BFF", "#7262FD", "#5349E0", "#2F32C3", "#001BA7", "#00068C"];
114
+ };
115
+ readonly scale: {
116
+ readonly continuous: {
117
+ readonly range: readonly ["#f7fbff", "#08306b"];
118
+ };
119
+ };
120
+ readonly background: string;
121
+ readonly header: {
122
+ titleColor: string;
123
+ labelColor: string;
124
+ };
125
+ readonly axis: {
126
+ gridColor: string;
127
+ domainColor: string;
128
+ tickColor: string;
129
+ labelColor: string;
130
+ titleColor: string;
131
+ };
132
+ readonly legend: {
133
+ labelColor: string;
134
+ titleColor: string;
135
+ };
136
+ readonly view: {
137
+ stroke: string;
138
+ };
139
+ };
140
+ };
141
+ export declare const builtInThemes: {
142
+ [themeKey: string]: {
143
+ light: any;
144
+ dark: any;
145
+ };
146
+ };
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
+ import { IDarkMode } from '../interfaces';
2
3
  import { IReactVegaHandler } from '../vis/react-vega';
3
- export declare const LiteContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
4
4
  interface IVisualSettings {
5
+ darkModePreference: IDarkMode;
5
6
  rendererHandler?: React.RefObject<IReactVegaHandler>;
6
7
  }
7
8
  declare const _default: React.FunctionComponent<IVisualSettings>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanaries/graphic-walker",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
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,10 +4,9 @@ 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, ISegmentKey } from "./interfaces";
7
+ import { IDarkMode, IMutField, IRow, ISegmentKey, IThemeKey } from "./interfaces";
8
8
  import type { IReactVegaHandler } from "./vis/react-vega";
9
9
  import VisualSettings from "./visualSettings";
10
- import { Container, NestContainer } from "./components/container";
11
10
  import ClickMenu from "./components/clickMenu";
12
11
  import InsightBoard from "./insightBoard/index";
13
12
  import PosFields from "./fields/posFields";
@@ -23,6 +22,7 @@ import FilterField from "./fields/filterField";
23
22
  import { guardDataKeys } from "./utils/dataPrep";
24
23
  import SegmentNav from "./segments/segmentNav";
25
24
  import DatasetConfig from "./dataSource/datasetConfig";
25
+ import { useCurrentMediaTheme } from "./utils/media";
26
26
 
27
27
  export interface IGWProps {
28
28
  dataSource?: IRow[];
@@ -36,9 +36,12 @@ export interface IGWProps {
36
36
  * auto parse field key into a safe string. default is true
37
37
  */
38
38
  fieldKeyGuard?: boolean;
39
+ /** @default "vega" */
40
+ themeKey?: IThemeKey;
41
+ dark?: IDarkMode;
39
42
  }
40
43
 
41
- const App: React.FC<IGWProps> = (props) => {
44
+ const App = observer<IGWProps>(function App (props) {
42
45
  const {
43
46
  dataSource = [],
44
47
  rawFields = [],
@@ -47,6 +50,8 @@ const App: React.FC<IGWProps> = (props) => {
47
50
  i18nResources,
48
51
  hideDataSourceConfig,
49
52
  fieldKeyGuard = true,
53
+ themeKey = 'vega',
54
+ dark = 'media',
50
55
  } = props;
51
56
  const { commonStore, vizStore } = useGlobalStore();
52
57
  const [insightReady, setInsightReady] = useState<boolean>(true);
@@ -114,14 +119,16 @@ const App: React.FC<IGWProps> = (props) => {
114
119
  };
115
120
  }, [currentDataset, spec]);
116
121
 
122
+ const darkMode = useCurrentMediaTheme(dark);
123
+
117
124
  const rendererRef = useRef<IReactVegaHandler>(null);
118
125
 
119
126
  return (
120
- <div className="App">
127
+ <div className={`${darkMode === 'dark' ? 'dark' : ''} App font-sans bg-white dark:bg-zinc-900 dark:text-white m-0 p-0`}>
121
128
  {/* <div className="grow-0">
122
129
  <PageNav />
123
130
  </div> */}
124
- <div className="">
131
+ <div className="bg-white dark:bg-zinc-900 dark:text-white">
125
132
  {!hideDataSourceConfig && <DataSourceSegment preWorkDone={insightReady} />}
126
133
  <div className="px-2 mx-2">
127
134
  <SegmentNav />
@@ -130,8 +137,8 @@ const App: React.FC<IGWProps> = (props) => {
130
137
  }
131
138
  </div>
132
139
  {segmentKey === ISegmentKey.vis && (
133
- <Container style={{ marginTop: "0em", borderTop: "none" }}>
134
- <VisualSettings rendererHandler={rendererRef} />
140
+ <div style={{ marginTop: "0em", borderTop: "none" }} className="m-4 p-4 border border-gray-200 dark:border-gray-700">
141
+ <VisualSettings rendererHandler={rendererRef} darkModePreference={dark} />
135
142
  <div className="md:grid md:grid-cols-12 xl:grid-cols-6">
136
143
  <div className="md:col-span-3 xl:col-span-1">
137
144
  <DatasetFields />
@@ -144,7 +151,8 @@ const App: React.FC<IGWProps> = (props) => {
144
151
  <div>
145
152
  <PosFields />
146
153
  </div>
147
- <NestContainer
154
+ <div
155
+ className="m-0.5 p-1 border border-gray-200 dark:border-gray-700"
148
156
  style={{ minHeight: "600px", overflow: "auto" }}
149
157
  onMouseLeave={() => {
150
158
  vizEmbededMenu.show && commonStore.closeEmbededMenu();
@@ -153,12 +161,12 @@ const App: React.FC<IGWProps> = (props) => {
153
161
  vizEmbededMenu.show && commonStore.closeEmbededMenu();
154
162
  }}
155
163
  >
156
- {datasets.length > 0 && <ReactiveRenderer ref={rendererRef} />}
164
+ {datasets.length > 0 && <ReactiveRenderer ref={rendererRef} themeKey={themeKey} dark={dark} />}
157
165
  <InsightBoard />
158
166
  {vizEmbededMenu.show && (
159
167
  <ClickMenu x={vizEmbededMenu.position[0]} y={vizEmbededMenu.position[1]}>
160
168
  <div
161
- className="flex items-center whitespace-nowrap py-1 px-4 hover:bg-gray-100"
169
+ className="flex items-center whitespace-nowrap py-1 px-4 hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer"
162
170
  onClick={() => {
163
171
  commonStore.closeEmbededMenu();
164
172
  commonStore.setShowInsightBoard(true);
@@ -171,19 +179,19 @@ const App: React.FC<IGWProps> = (props) => {
171
179
  </div>
172
180
  </ClickMenu>
173
181
  )}
174
- </NestContainer>
182
+ </div>
175
183
  </div>
176
184
  </div>
177
- </Container>
185
+ </div>
178
186
  )}
179
187
  {segmentKey === ISegmentKey.data && (
180
- <Container style={{ marginTop: "0em", borderTop: "none" }}>
188
+ <div className="m-4 p-4 border border-gray-200 dark:border-gray-700" style={{ marginTop: "0em", borderTop: "none" }}>
181
189
  <DatasetConfig />
182
- </Container>
190
+ </div>
183
191
  )}
184
192
  </div>
185
193
  </div>
186
194
  );
187
- };
195
+ });
188
196
 
189
- export default observer(App);
197
+ 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;
@@ -1,14 +1,17 @@
1
1
  import React, { memo, ReactNode, useContext, useEffect, useState } from "react";
2
2
  import { createPortal } from "react-dom";
3
3
  import styled from "styled-components";
4
+ import type { IDarkMode } from "../interfaces";
4
5
  import { ShadowDomContext } from "..";
6
+ import { useCurrentMediaTheme } from "../utils/media";
5
7
 
6
8
  export interface CalloutProps {
7
9
  target: string;
8
10
  children: ReactNode;
11
+ darkModePreference?: IDarkMode;
9
12
  }
10
13
 
11
- const Bubble = styled.div`
14
+ const Bubble = styled.div<{ dark: boolean }>`
12
15
  border-radius: 1px;
13
16
  transform: translate(-50%, 0);
14
17
  filter: drop-shadow(0 1.6px 1px rgba(0, 0, 0, 0.24)) drop-shadow(0 -1px 0.8px rgba(0, 0, 0, 0.19));
@@ -25,12 +28,12 @@ const Bubble = styled.div`
25
28
  width: 8px;
26
29
  height: 8px;
27
30
  transform: translate(-50%, -50%) rotate(45deg);
28
- background-color: #fff;
31
+ background-color: ${({ dark }) => dark ? "#000" : "#fff"};
29
32
  border-radius: 1px;
30
33
  }
31
34
  `;
32
35
 
33
- const Callout = memo<CalloutProps>(function Callout({ target, children }) {
36
+ const Callout = memo<CalloutProps>(function Callout({ target, children, darkModePreference = 'media' }) {
34
37
  const shadowDomMeta = useContext(ShadowDomContext);
35
38
  const { root } = shadowDomMeta;
36
39
  const [pos, setPos] = useState<[number, number] | null>(null);
@@ -45,11 +48,13 @@ const Callout = memo<CalloutProps>(function Callout({ target, children }) {
45
48
  }
46
49
  }, [target, root]);
47
50
 
51
+ const darkMode = useCurrentMediaTheme(darkModePreference);
52
+
48
53
  return (
49
54
  root &&
50
55
  pos &&
51
56
  createPortal(
52
- <Bubble role="dialog" className="fixed bg-white z-50" style={{ left: pos[0], top: pos[1] + 4 }}>
57
+ <Bubble role="dialog" dark={darkMode === 'dark'} className="fixed bg-white dark:bg-zinc-900 z-50" style={{ left: pos[0], top: pos[1] + 4 }}>
53
58
  {children}
54
59
  </Bubble>,
55
60
  root
@@ -3,13 +3,9 @@ import styled from "styled-components";
3
3
 
4
4
  const MenuContainer = styled.div`
5
5
  min-width: 100px;
6
- background-color: #fff;
7
- border: 1px solid #f0f0f0;
8
6
  position: absolute;
9
7
  z-index: 99;
10
8
  cursor: pointer;
11
- /* box-shadow: 0px 0px 8px 1px rgba(0, 0, 0, 0.09); */
12
- /* border-radius: 2px; */
13
9
  padding: 4px;
14
10
  `;
15
11
  interface ClickMenuProps {
@@ -20,7 +16,7 @@ interface ClickMenuProps {
20
16
  const ClickMenu: React.FC<ClickMenuProps> = (props) => {
21
17
  const { x, y, children } = props;
22
18
  return (
23
- <MenuContainer className="shadow-lg text-sm" style={{ left: x + "px", top: y + "px" }}>
19
+ <MenuContainer className="shadow-lg text-sm bg-white border border-gray-100 dark:bg-black dark:border-gray-700" style={{ left: x + "px", top: y + "px" }}>
24
20
  {children}
25
21
  </MenuContainer>
26
22
  );