vzcode 0.24.0 → 0.26.0

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 (41) hide show
  1. package/dist/assets/{index-9c8bbae0.js → index-284b7339.js} +50 -50
  2. package/dist/assets/index-e160f758.css +1 -0
  3. package/dist/index.html +2 -6
  4. package/package.json +7 -5
  5. package/src/client/App.tsx +47 -213
  6. package/src/client/CodeEditor/getOrCreateEditor.ts +3 -0
  7. package/src/client/CodeEditor/index.tsx +36 -6
  8. package/src/client/CodeEditor/{json1PresenceBroadcast.js → json1PresenceBroadcast.ts} +5 -3
  9. package/src/client/CodeEditor/{json1PresenceDisplay.js → json1PresenceDisplay.ts} +9 -3
  10. package/src/client/CodeEditor/widgets.ts +112 -10
  11. package/src/client/PresenceNotifications/index.tsx +0 -2
  12. package/src/client/TabList/Tab.tsx +56 -0
  13. package/src/client/TabList/index.tsx +11 -62
  14. package/src/client/TabList/style.scss +21 -9
  15. package/src/client/{Settings.tsx → VZSettings.tsx} +1 -1
  16. package/src/client/{Sidebar → VZSidebar}/FileListing.tsx +3 -0
  17. package/src/client/{Sidebar → VZSidebar}/Item.tsx +10 -7
  18. package/src/client/{Sidebar → VZSidebar}/Listing.tsx +3 -0
  19. package/src/client/{Sidebar → VZSidebar}/index.tsx +5 -6
  20. package/src/client/{Sidebar → VZSidebar}/styles.scss +17 -12
  21. package/src/client/bootstrap.ts +3 -0
  22. package/src/client/style.scss +5 -2
  23. package/src/client/themes/index.ts +7 -0
  24. package/src/client/{themes.ts → themes/themes.ts} +5 -5
  25. package/src/client/{useDynamicTheme.ts → themes/useDynamicTheme.ts} +1 -1
  26. package/src/client/themes/vizhubTheme/colors.ts +80 -0
  27. package/src/client/themes/vizhubTheme/index.ts +166 -0
  28. package/src/client/useActions.ts +74 -0
  29. package/src/client/useFileCRUD.ts +101 -0
  30. package/src/client/useOpenDirectories.ts +25 -7
  31. package/src/client/useSubmitOperation.ts +25 -0
  32. package/src/client/vzReducer.ts +118 -0
  33. package/src/index.ts +34 -0
  34. package/src/server/index.js +13 -2
  35. package/dist/assets/index-cf19de3b.css +0 -1
  36. package/src/client/reducer.ts +0 -122
  37. package/src/client/useTabsState.ts +0 -95
  38. package/src/client/vizhubTheme.js +0 -1
  39. /package/src/client/{Sidebar → VZSidebar}/ConfirmationBox.tsx +0 -0
  40. /package/src/client/{Sidebar → VZSidebar}/DirectoryArrowSVG.jsx +0 -0
  41. /package/src/client/{Sidebar → VZSidebar}/DirectoryListing.tsx +0 -0
@@ -0,0 +1,56 @@
1
+ import { useCallback, useMemo } from 'react';
2
+ import { FileId } from '../../types';
3
+
4
+ // Supports adding the file's containing folder to the tab name
5
+ const fileNameSplit = (fileName: string) => {
6
+ const split = fileName.split('/');
7
+ if (split.length === 1) return split[split.length - 1];
8
+ return (
9
+ split[split.length - 2] + '/' + split[split.length - 1]
10
+ );
11
+ };
12
+
13
+ export const Tab = ({
14
+ fileId,
15
+ isActive,
16
+ setActiveFileId,
17
+ closeTabs,
18
+ fileName,
19
+ }: {
20
+ fileId: FileId;
21
+ isActive: boolean;
22
+ setActiveFileId: (fileId: FileId) => void;
23
+ closeTabs: (fileIds: FileId[]) => void;
24
+ fileName: string;
25
+ }) => {
26
+ const handleCloseClick = useCallback(
27
+ (event: React.MouseEvent) => {
28
+ // Stop propagation so that the outer listener doesn't fire.
29
+ event.stopPropagation();
30
+
31
+ closeTabs([fileId]);
32
+ },
33
+ [closeTabs, fileId],
34
+ );
35
+
36
+ const tabName = useMemo(
37
+ () => fileNameSplit(fileName),
38
+ [fileName],
39
+ );
40
+
41
+ return (
42
+ <div
43
+ className={isActive ? 'tab active' : 'tab'}
44
+ onClick={() => {
45
+ setActiveFileId(fileId);
46
+ }}
47
+ >
48
+ {tabName}
49
+ <div
50
+ // className={isActive ? 'bx bx-x tab-close' : ''}
51
+ className={'bx bx-x tab-close'}
52
+ onClick={handleCloseClick}
53
+ ></div>
54
+ </div>
55
+ );
56
+ };
@@ -1,89 +1,37 @@
1
- import { useCallback, useMemo, useEffect } from 'react';
1
+ import { useCallback, useEffect } from 'react';
2
2
  import { FileId, Files } from '../../types';
3
+ import { Tab } from './Tab';
3
4
  import './style.scss';
4
5
 
5
- // Supports adding the file's containing folder to the tab name
6
- const fileNameSplit = (fileName) => {
7
- const split = fileName.split('/');
8
- if (split.length === 1) return split[split.length - 1];
9
- return (
10
- split[split.length - 2] + '/' + split[split.length - 1]
11
- );
12
- };
13
-
14
- const Tab = ({
15
- fileId,
16
- isActive,
17
- setActiveFileId,
18
- closeTab,
19
- fileName,
20
- }: {
21
- fileId: FileId;
22
- isActive: boolean;
23
- setActiveFileId: (fileId: FileId) => void;
24
- closeTab: (fileId: FileId) => void;
25
- fileName: string;
26
- }) => {
27
- const handleCloseClick = useCallback(
28
- (event: React.MouseEvent) => {
29
- // Stop propagation so that the outer listener doesn't fire.
30
- event.stopPropagation();
31
-
32
- closeTab(fileId);
33
- },
34
- [closeTab, fileId],
35
- );
36
-
37
- const tabName = useMemo(
38
- () => fileNameSplit(fileName),
39
- [fileName],
40
- );
41
-
42
- return (
43
- <div
44
- className={isActive ? 'tab active' : 'tab'}
45
- onClick={() => {
46
- setActiveFileId(fileId);
47
- }}
48
- >
49
- {tabName}
50
- <div
51
- className={isActive ? 'bx bx-x tab-close' : ''}
52
- onClick={handleCloseClick}
53
- ></div>
54
- </div>
55
- );
56
- };
57
-
58
6
  // Displays the list of tabs above the code editor.
59
7
  export const TabList = ({
60
8
  files,
61
9
  tabList,
62
10
  activeFileId,
63
11
  setActiveFileId,
64
- closeTab,
12
+ closeTabs,
65
13
  }: {
66
14
  files: Files;
67
15
  tabList: FileId[];
68
16
  activeFileId: FileId;
69
17
  setActiveFileId: (fileId: FileId) => void;
70
- closeTab: (fileId: FileId) => void;
18
+ closeTabs: (fileIds: FileId[]) => void;
71
19
  }) => {
72
- //Create a function to perform the logic to delete the current tab
20
+ // Close the active tab on alt+w
73
21
  const handleKeyPress = useCallback(
74
22
  (event: { altKey: boolean; key: string }) => {
75
23
  if (event.altKey == true) {
76
24
  if (event.key == 'w') {
77
- closeTab(activeFileId);
25
+ closeTabs([activeFileId]);
78
26
  }
79
27
  }
80
28
  },
81
- [closeTab, activeFileId],
29
+ [closeTabs, activeFileId],
82
30
  );
31
+
32
+ // Add the global keydown event listener
83
33
  useEffect(() => {
84
- // attach the event listener
85
34
  document.addEventListener('keydown', handleKeyPress);
86
- // remove the event listener
87
35
  return () => {
88
36
  document.removeEventListener(
89
37
  'keydown',
@@ -91,6 +39,7 @@ export const TabList = ({
91
39
  );
92
40
  };
93
41
  }, [handleKeyPress]);
42
+
94
43
  return (
95
44
  <div className="vz-tab-list">
96
45
  {files &&
@@ -100,7 +49,7 @@ export const TabList = ({
100
49
  fileId={fileId}
101
50
  isActive={fileId === activeFileId}
102
51
  setActiveFileId={setActiveFileId}
103
- closeTab={closeTab}
52
+ closeTabs={closeTabs}
104
53
  fileName={files[fileId].name}
105
54
  />
106
55
  ))}
@@ -1,20 +1,20 @@
1
1
  .vz-tab-list {
2
2
  display: flex;
3
- background-color: rgb(37, 37, 38);
3
+ background-color: #33415b;
4
4
  // When the tab list becomes too large, a horizontal scroll bar appears.
5
5
  overflow-x: auto;
6
6
 
7
7
  .tab {
8
- background: rgb(45, 45, 45);
8
+ // background: #47546b;
9
9
  color: #fff;
10
10
  font-family: var(--vzcode-font-family);
11
11
  align-items: center;
12
12
  display: flex;
13
13
  padding-top: 2px;
14
- padding-left: 10px;
15
- padding-right: 10px;
16
- border-top-left-radius: 10px;
17
- border-top-right-radius: 10px;
14
+ padding-left: 8px;
15
+ padding-right: 5px;
16
+ border-top-left-radius: 12px;
17
+ border-top-right-radius: 12px;
18
18
  margin-top: 5px;
19
19
  margin-left: 2px;
20
20
  margin-right: 2px;
@@ -24,13 +24,25 @@
24
24
 
25
25
  .tab-close {
26
26
  margin-left: 5px;
27
+ margin-bottom: 2px;
27
28
  }
28
29
  .tab-close:hover {
29
- border-radius: 30%;
30
- background-color: rgb(37, 37, 38);
30
+ border-radius: 50%;
31
+ background-color: rgba(255, 255, 255, 0.2);
32
+ }
33
+
34
+ // No left margin for first child
35
+ &:first-child {
36
+ margin-left: 0;
37
+ }
38
+
39
+ // on hover
40
+ &:hover {
41
+ background-color: #47546b;
31
42
  }
32
43
  }
44
+
33
45
  .tab.active {
34
- background-color: rgb(41, 44, 52);
46
+ background-color: #202e46;
35
47
  }
36
48
  }
@@ -11,7 +11,7 @@ import { ThemeLabel, themes } from './themes';
11
11
 
12
12
  export let username = 'Anonymous';
13
13
 
14
- export const Settings = ({
14
+ export const VZSettings = ({
15
15
  show,
16
16
  onClose,
17
17
  setTheme,
@@ -8,6 +8,7 @@ export const FileListing = ({
8
8
  handleRenameFileClick,
9
9
  handleDeleteFileClick,
10
10
  handleFileClick,
11
+ isActive,
11
12
  }: {
12
13
  name: string;
13
14
  fileId: FileId;
@@ -20,6 +21,7 @@ export const FileListing = ({
20
21
  event: React.MouseEvent,
21
22
  ) => void;
22
23
  handleFileClick: (fileId: FileId) => void;
24
+ isActive: boolean;
23
25
  }) => {
24
26
  const handleClick = useCallback(() => {
25
27
  handleFileClick(fileId);
@@ -46,6 +48,7 @@ export const FileListing = ({
46
48
  handleDeleteClick={handleDeleteClick}
47
49
  handleRenameClick={handleRenameClick}
48
50
  isDir={false}
51
+ isActive={isActive}
49
52
  >
50
53
  {name}
51
54
  </Item>
@@ -8,6 +8,7 @@ export const Item = ({
8
8
  handleRenameClick,
9
9
  handleDeleteClick,
10
10
  isDir,
11
+ isActive = false,
11
12
  }) => {
12
13
  // Tracks whether the mouse is hovering over the file or directory
13
14
  const [isHovered, setIsHovered] = useState(false);
@@ -19,9 +20,9 @@ export const Item = ({
19
20
  const [renameValue, setRenameValue] = useState('');
20
21
 
21
22
  const onKeyDown = useCallback((event) => {
22
- // TODO make 'Escape' cancel the changes - do not commit the rename
23
- // https://github.com/vizhub-core/vzcode/issues/207
24
- if (event.key === 'Enter' || event.key === 'Escape') {
23
+ if (event.key === 'Escape') {
24
+ setIsRenaming(false);
25
+ } else if (event.key === 'Enter') {
25
26
  event.target.blur();
26
27
  }
27
28
  }, []);
@@ -82,7 +83,9 @@ export const Item = ({
82
83
 
83
84
  return (
84
85
  <div
85
- className="full-box file-or-directory"
86
+ className={`full-box file-or-directory ${
87
+ isActive ? 'active-file' : ''
88
+ }`}
86
89
  onClick={isRenaming ? null : handleClick}
87
90
  onMouseEnter={handleMouseEnter}
88
91
  onMouseLeave={handleMouseLeave}
@@ -105,7 +108,7 @@ export const Item = ({
105
108
  <div className="utils">
106
109
  <i
107
110
  className="bx bxs-edit utilities"
108
- style={{ color: '#abdafb' }}
111
+ style={{ color: '#9edcff' }}
109
112
  onClick={(event: React.MouseEvent) => {
110
113
  event.stopPropagation();
111
114
  setIsRenaming(!isRenaming);
@@ -113,8 +116,8 @@ export const Item = ({
113
116
  }}
114
117
  ></i>
115
118
  <i
116
- className="bx bx-trash"
117
- style={{ color: '#eb336c' }}
119
+ className="bx bx-trash utilities"
120
+ style={{ color: '#ff006b' }}
118
121
  onClick={handleModalOpen}
119
122
  ></i>
120
123
  </div>
@@ -15,6 +15,7 @@ export const Listing = ({
15
15
  handleFileClick,
16
16
  isDirectoryOpen,
17
17
  toggleDirectory,
18
+ activeFileId,
18
19
  }: {
19
20
  entity: FileTree | FileTreeFile;
20
21
  handleRenameFileClick: (
@@ -28,6 +29,7 @@ export const Listing = ({
28
29
  handleFileClick: (fileId: FileId) => void;
29
30
  isDirectoryOpen: (path: string) => boolean;
30
31
  toggleDirectory: (path: string) => void;
32
+ activeFileId: FileId;
31
33
  }) => {
32
34
  const { name, file, fileId } = entity as FileTreeFile;
33
35
  const { path, children } = entity as FileTree;
@@ -38,6 +40,7 @@ export const Listing = ({
38
40
  handleRenameFileClick={handleRenameFileClick}
39
41
  handleDeleteFileClick={handleDeleteFileClick}
40
42
  handleFileClick={handleFileClick}
43
+ isActive={fileId === activeFileId}
41
44
  />
42
45
  ) : (
43
46
  <DirectoryListing
@@ -12,7 +12,7 @@ import { SplitPaneResizeContext } from '../SplitPaneResizeContext';
12
12
  import { Listing } from './Listing';
13
13
  import './styles.scss';
14
14
 
15
- export const Sidebar = ({
15
+ export const VZSidebar = ({
16
16
  createFile,
17
17
  files,
18
18
  handleRenameFileClick,
@@ -21,6 +21,7 @@ export const Sidebar = ({
21
21
  setIsSettingsOpen,
22
22
  isDirectoryOpen,
23
23
  toggleDirectory,
24
+ activeFileId,
24
25
  }: {
25
26
  files: Files;
26
27
  createFile?: () => void;
@@ -36,6 +37,7 @@ export const Sidebar = ({
36
37
  setIsSettingsOpen?: (isSettingsOpen: boolean) => void;
37
38
  isDirectoryOpen?: (path: string) => boolean;
38
39
  toggleDirectory?: (path: string) => void;
40
+ activeFileId?: FileId;
39
41
  }) => {
40
42
  const fileTree = useMemo(
41
43
  () => (files ? sortFileTree(getFileTree(files)) : null),
@@ -57,11 +59,7 @@ export const Sidebar = ({
57
59
  >
58
60
  <div className="files">
59
61
  <div className="full-box">
60
- <div>
61
- <a className="link-name" href="#">
62
- Files
63
- </a>
64
- </div>
62
+ <div className="sidebar-section-hint">Files</div>
65
63
  <div>
66
64
  <i
67
65
  className="bx bxs-file-plus new-btn"
@@ -88,6 +86,7 @@ export const Sidebar = ({
88
86
  handleFileClick={handleFileClick}
89
87
  isDirectoryOpen={isDirectoryOpen}
90
88
  toggleDirectory={toggleDirectory}
89
+ activeFileId={activeFileId}
91
90
  />
92
91
  );
93
92
  })
@@ -1,12 +1,13 @@
1
1
  .vz-sidebar {
2
2
  height: 100%;
3
- background: rgb(54, 65, 89);
3
+ color: #d6d9de;
4
+ background: #33415b;
4
5
  display: flex;
5
6
  flex-direction: column;
6
7
  justify-content: space-between;
7
8
 
8
9
  .full-box {
9
- padding: 7px;
10
+ padding: 3px 6px;
10
11
  display: flex;
11
12
  flex-direction: row;
12
13
  align-items: center;
@@ -24,16 +25,14 @@
24
25
  justify-content: space-between;
25
26
  cursor: pointer;
26
27
  margin: 0 10px;
27
- color: rgb(219, 221, 225);
28
- border-radius: 5px;
28
+ border-radius: 4px;
29
29
  }
30
30
 
31
- .link-name {
32
- margin-top: 30px;
31
+ .sidebar-section-hint {
32
+ // margin-top: 30px;
33
33
  margin-left: 10px;
34
- color: rgb(154, 160, 172);
35
34
  font-size: 12px;
36
- text-decoration: none;
35
+ color: #99a0ad;
37
36
  }
38
37
 
39
38
  .new-btn {
@@ -44,14 +43,21 @@
44
43
 
45
44
  .utils {
46
45
  display: flex;
46
+ gap: 8px;
47
47
  }
48
48
  .utilities {
49
- margin-right: 3px;
49
+ // margin-right: 3px;
50
+ transform: scale(1.2);
50
51
  }
51
52
 
52
53
  .file-or-directory:hover,
53
54
  .settings:hover {
54
- background-color: rgb(74, 84, 105);
55
+ background-color: #47546b;
56
+ }
57
+
58
+ .active-file,
59
+ .active-file:hover {
60
+ background-color: #202e46;
55
61
  }
56
62
 
57
63
  .name {
@@ -71,13 +77,12 @@
71
77
 
72
78
  .settings {
73
79
  height: 30px;
74
- color: rgb(219, 221, 225);
75
80
  cursor: pointer;
76
81
  display: flex;
77
82
  align-items: center;
78
83
  justify-content: center;
79
84
  padding: 14px 0;
80
85
  margin: 10px;
81
- border-radius: 5px;
86
+ border-radius: 4px;
82
87
  }
83
88
  }
@@ -5,4 +5,7 @@ import Form from 'react-bootstrap/cjs/Form.js';
5
5
  import Button from 'react-bootstrap/cjs/Button.js';
6
6
  import Modal from 'react-bootstrap/cjs/Modal.js';
7
7
 
8
+ // Pull in custom CSS from vizhub-ui.
9
+ import 'vizhub-ui/dist/vizhub-ui.css';
10
+
8
11
  export { Form, Button, Modal };
@@ -1,6 +1,7 @@
1
1
  :root {
2
2
  --vzcode-font-family: ui-monospace, SFMono-Regular,
3
- SF Mono, Menlo, Consolas, Liberation Mono, monospace;
3
+ 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace !important;
4
+ /* Variable for the background color */
4
5
  --vz-bg-color: rgb(
5
6
  41,
6
7
  44,
@@ -36,7 +37,9 @@ body,
36
37
 
37
38
  .app {
38
39
  background-color: var(--vz-bg-color);
39
- font-family: 'Poppins', sans-serif;
40
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI',
41
+ 'Noto Sans', Helvetica, Arial, sans-serif,
42
+ 'Apple Color Emoji', 'Segoe UI Emoji';
40
43
  display: flex;
41
44
 
42
45
  /* To support Resizer, which is position: absolute */
@@ -0,0 +1,7 @@
1
+ export {
2
+ themes,
3
+ defaultTheme,
4
+ themeOptionsByLabel,
5
+ } from './themes';
6
+ export type { ThemeLabel, ThemeOption } from './themes';
7
+ export { useDynamicTheme } from './useDynamicTheme';
@@ -7,7 +7,7 @@ import { githubDark } from '@uiw/codemirror-theme-github';
7
7
  import { material } from '@uiw/codemirror-theme-material';
8
8
  import { nord } from '@uiw/codemirror-theme-nord';
9
9
  import { xcodeLight } from '@uiw/codemirror-theme-xcode';
10
- // import { vizhub } from './vizhub-theme';
10
+ import { vizhubTheme } from './vizhubTheme';
11
11
 
12
12
  // CodeMirror themes
13
13
  export type ThemeLabel =
@@ -19,8 +19,8 @@ export type ThemeLabel =
19
19
  | 'oneDark'
20
20
  | 'okaidia'
21
21
  | 'github'
22
- | 'xcode';
23
- // | 'vizhub'
22
+ | 'xcode'
23
+ | 'vizhub';
24
24
 
25
25
  export type ThemeOption = {
26
26
  value: any;
@@ -37,7 +37,7 @@ export const themes: Array<ThemeOption> = [
37
37
  { value: okaidia, label: 'okaidia' },
38
38
  { value: githubDark, label: 'github' },
39
39
  { value: xcodeLight, label: 'xcode' },
40
- // { value: vizhub, label: 'vizhub' },
40
+ { value: vizhubTheme, label: 'vizhub' },
41
41
  ];
42
42
 
43
43
  // Map theme labels to theme values
@@ -53,4 +53,4 @@ export const themeOptionsByLabel: Record<
53
53
  );
54
54
 
55
55
  // The default theme
56
- export const defaultTheme: ThemeLabel = 'oneDark';
56
+ export const defaultTheme: ThemeLabel = 'vizhub';
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useRef } from 'react';
2
- import { EditorCache } from './useEditorCache';
2
+ import { EditorCache } from '../useEditorCache';
3
3
  import { ThemeLabel, themeOptionsByLabel } from './themes';
4
4
 
5
5
  export const useDynamicTheme = (
@@ -0,0 +1,80 @@
1
+ // import { hcl } from 'd3-color';
2
+
3
+ // This module defines all the colors for the VizHub theme.
4
+ // Ported from the CodeMirror 5 theme defined here:
5
+ // https://github.com/vizhub-core/vizhub-legacy/blob/01cadfb78a2611df32f981b1fd8136b70447de9e/vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/themes/vizHub.js
6
+
7
+ // This is how the colors were generated:
8
+ // const sidebarDark = hcl('#3d4b65');
9
+ // const sidebarLight = hcl('#5b677d');
10
+ // const luminaceDifference = sidebarLight.l - sidebarDark.l;
11
+ // const backgroundLuminance =
12
+ // sidebarDark.l - luminaceDifference * 1.1;
13
+ // const luminance = 90;
14
+ // export const backgroundColor = hcl(
15
+ // sidebarDark.h,
16
+ // sidebarDark.c,
17
+ // backgroundLuminance,
18
+ // ).formatHex();
19
+ // export const light = hcl(0, 0, luminance).formatHex();
20
+ // export const dark = hcl(
21
+ // sidebarDark.h,
22
+ // sidebarDark.c,
23
+ // 80,
24
+ // ).formatHex();
25
+ // console.log(
26
+ // JSON.stringify(
27
+ // {
28
+ // backgroundColor,
29
+ // light,
30
+ // dark,
31
+ // },
32
+ // null,
33
+ // 2,
34
+ // ),
35
+ // );
36
+
37
+ // These are inlined from the above code, but the code is kept around for future reference.
38
+ export const backgroundColor = '#202e46';
39
+ export const light = '#e2e2e2';
40
+ export const dark = '#b9c7e6';
41
+
42
+ export const lineNumbers = 'rgba(255,255,255,0.2)';
43
+ export const lineNumbersActive = 'rgba(255,255,255,0.5)';
44
+ export const selectionBackground = '#000';
45
+ export const selectionBackgroundMatch = 'rgba(0,0,0,0.4)';
46
+ export const lineHighlight = 'rgba(0,0,0,0.1)';
47
+ export const caretColor = 'white';
48
+
49
+ // Compute 6 colors that are evenly spaced in terms of hue
50
+ // Keeping this code around for future reference
51
+ // const rotation = 0.397;
52
+ // const numColors = 6;
53
+ // const highlightColors = Array.from(
54
+ // { length: numColors },
55
+ // (_, i) => {
56
+ // let t = (i / numColors + rotation) % 1;
57
+ // return hcl(t * 360, saturation, luminance).formatHex();
58
+ // },
59
+ // );
60
+ // console.log(JSON.stringify(highlightColors));
61
+
62
+ // We inline the colors here, but the code above is how they were generated.
63
+ const highlightColors = [
64
+ '#77fd8c',
65
+ '#00ffff',
66
+ '#66ecff',
67
+ '#ffb9ff',
68
+ '#ffabb3',
69
+ '#ffdb56',
70
+ ];
71
+
72
+ export const MINT = highlightColors[0];
73
+ export const AQUA = highlightColors[1];
74
+ export const SKY = highlightColors[2];
75
+ export const LAVENDER = highlightColors[3];
76
+ export const SALMON = highlightColors[4];
77
+ export const GOLDENROD = highlightColors[5];
78
+
79
+ // Red that's not too bright, for errors
80
+ export const PANIC = '#ff2222';