Skip to content

Commit

Permalink
adding theme editor to Gosling editor
Browse files Browse the repository at this point in the history
  • Loading branch information
sehilyi committed Nov 15, 2024
1 parent bde823c commit d5d6282
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 24 deletions.
66 changes: 49 additions & 17 deletions editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { getHtmlTemplate } from './html-template';
import ErrorBoundary from './error-boundary';
import { traverseTracksAndViews } from '../src/compiler/spec-preprocess';
import { examples, type Example } from './example';
import EditorPanel, { type EditorLangauge } from './EditorPanel';
import EditorPanel, { type EditorCodeType } from './EditorPanel';
import EditorExamples from './EditorExamples';

import './Editor.css';
Expand Down Expand Up @@ -131,6 +131,8 @@ const validateExampleId = (id: string): boolean => {

const getDescPanelDefultWidth = () => Math.min(500, window.innerWidth);

const isDarkTheme = (t: gosling.Theme) => (typeof t !== 'string' && 'base' in t ? t.base === 'dark' : t === 'dark');

/**
* Convert relative CSV data URLs to absolute URLs.
* (e.g., './example.csv' => 'https://gist.githubusercontent.com/{urlGist}/raw/example.csv')
Expand Down Expand Up @@ -237,7 +239,7 @@ function Editor(props: RouteComponentProps) {
examples[urlExampleId] ? { id: urlExampleId, ...examples[urlExampleId] } : INIT_DEMO
);
const [isImportDemo, setIsImportDemo] = useState<boolean>(false);
const [theme, setTheme] = useState<gosling.Theme>('light'); // or `{ base: 'light', axis: { labelMargin: -1 } }`
const [theme, setTheme] = useState<gosling.Theme>({ base: 'light' }); // 'light' or `{ base: 'light', axis: { labelMargin: -1 } }`
const [hg, setHg] = useState<HiGlassSpec>();
const [code, setCode] = useState(defaultCode);
const [jsCode, setJsCode] = useState(defaultJsCode); //[TO-DO: more js format examples]
Expand Down Expand Up @@ -300,9 +302,11 @@ function Editor(props: RouteComponentProps) {
const gosRef = useRef<gosling.GoslingRef>(null);

const debounceCodeEdit = useRef(
debounce((code: string, language: EditorLangauge) => {
if (language == 'json') {
debounce((code: string, codeType: EditorCodeType) => {
if (codeType == 'gosling-json') {
setCode(code);
} else if (codeType == 'gosling-theme') {
setTheme(JSON.parse(code));
} else {
setJsCode(code);
}
Expand Down Expand Up @@ -744,7 +748,7 @@ function Editor(props: RouteComponentProps) {
return (
<>
<div
className={`demo-navbar ${theme === 'dark' ? 'dark' : ''}`}
className={`demo-navbar ${isDarkTheme(theme) ? 'dark' : ''}`}
// To test APIs, uncomment the following code.
// onClick={() => {
// if (!gosRef.current) return;
Expand Down Expand Up @@ -849,10 +853,10 @@ function Editor(props: RouteComponentProps) {
) : null}
</div>
{/* ------------------------ Main View ------------------------ */}
<div className={`editor ${theme === 'dark' ? 'dark' : ''}`}>
<div className={`editor ${isDarkTheme(theme) ? 'dark' : ''}`}>
<Allotment vertical={false}>
<Allotment.Pane minSize={50} maxSize={50}>
<div className={`side-panel ${theme === 'dark' ? 'dark' : ''}`}>
<div className={`side-panel ${isDarkTheme(theme) ? 'dark' : ''}`}>
<button
title="Example Gallery"
className="side-panel-button"
Expand Down Expand Up @@ -1149,46 +1153,74 @@ function Editor(props: RouteComponentProps) {
</span>
</span>
</button>
<button
className={`tablinks ${language == 'theme' && 'active'}`}
onClick={() => {
changeLanguage('theme');
setLog({ message: '', state: 'success' });
}}
>
Theme{` `}
<span className="tooltip">
{getIconSVG(ICONS.INFO_CIRCLE, 10, 10)}
<span className="tooltiptext">
Change the style of Gosling visualizations, such as background
color.
</span>
</span>
</button>
</div>

<div className={`tabContent ${language == 'json' ? 'show' : 'hide'}`}>
<EditorPanel
code={code}
codeType={'gosling-json'}
readOnly={readOnly}
openFindBox={isFindCode}
fontZoomIn={isFontZoomIn}
fontZoomOut={isFontZoomOut}
onChange={debounceCodeEdit.current}
isDarkTheme={theme === 'dark'}
language="json"
isDarkTheme={isDarkTheme(theme)}
/>
</div>
<div className={`tabContent ${language == 'typescript' ? 'show' : 'hide'}`}>
<EditorPanel
code={jsCode}
codeType={'gosling-ts'}
readOnly={readOnly}
openFindBox={isFindCode}
fontZoomIn={isFontZoomIn}
fontZoomOut={isFontZoomOut}
onChange={debounceCodeEdit.current}
isDarkTheme={isDarkTheme(theme)}
/>
</div>
<div className={`tabContent ${language == 'theme' ? 'show' : 'hide'}`}>
<EditorPanel
code={JSON.stringify(theme)}
codeType={'gosling-theme'}
readOnly={readOnly}
openFindBox={isFindCode}
fontZoomIn={isFontZoomIn}
fontZoomOut={isFontZoomOut}
onChange={debounceCodeEdit.current}
isDarkTheme={theme === 'dark'}
language="typescript"
isDarkTheme={isDarkTheme(theme)}
/>
</div>
</div>
<div className={`compile-message compile-message-${log.state}`}>{log.message}</div>
</>
{/* HiGlass View Config */}
<Allotment.Pane preferredSize={BOTTOM_PANEL_HEADER_HEIGHT}>
<div className={`editor-header ${theme === 'dark' ? 'dark' : ''}`}>
<div className={`editor-header ${isDarkTheme(theme) ? 'dark' : ''}`}>
Compiled HiGlass ViewConfig (Read Only)
</div>
<div style={{ height: '100%', visibility: showVC ? 'visible' : 'hidden' }}>
<EditorPanel
code={stringify(hg)}
codeType={'higlass'}
readOnly={true}
isDarkTheme={theme === 'dark'}
language="json"
isDarkTheme={isDarkTheme(theme)}
/>
</div>
</Allotment.Pane>
Expand All @@ -1198,7 +1230,7 @@ function Editor(props: RouteComponentProps) {
<Allotment ref={displayPanelRef} vertical={true}>
<div
id="preview-container"
className={`preview-container ${theme === 'dark' ? 'dark' : ''}`}
className={`preview-container ${isDarkTheme(theme) ? 'dark' : ''}`}
>
{isResponsive && !IS_SMALL_SCREEN ? ResponsiveWidget : null}
<div
Expand Down Expand Up @@ -1261,7 +1293,7 @@ function Editor(props: RouteComponentProps) {
minSize={BOTTOM_PANEL_HEADER_HEIGHT}
>
<button
className={`editor-header ${theme === 'dark' ? 'dark' : ''}`}
className={`editor-header ${isDarkTheme(theme) ? 'dark' : ''}`}
style={{ cursor: 'pointer' }}
>
Data Preview (~100 Rows, Data Before Transformation)
Expand Down Expand Up @@ -1341,7 +1373,7 @@ function Editor(props: RouteComponentProps) {
<div
className={`description ${hideDescription ? '' : 'description-shadow '}${
isDescResizing ? '' : 'description-transition'
} ${theme === 'dark' ? 'dark' : ''}`}
} ${isDarkTheme(theme) ? 'dark' : ''}`}
style={{ width: !description || hideDescription ? 0 : descPanelWidth }}
>
<div
Expand Down
19 changes: 12 additions & 7 deletions editor/EditorPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ import React, { useRef, useState, useEffect } from 'react'; // eslint-disable-li
import MonacoEditor from 'react-monaco-editor';

import ReactResizeDetector from 'react-resize-detector';
import { GoslingSchema } from 'gosling.js';
import { GoslingSchema, ThemeSchema } from 'gosling.js';
import goslingSpec from '../src/gosling-schema/gosling.schema?raw';

export * from './monaco_worker';
import * as Monaco from 'monaco-editor';

export type EditorLangauge = 'json' | 'typescript';
export type EditorCodeType = 'gosling-json' | 'gosling-ts' | 'gosling-theme' | 'higlass';

function EditorPanel(props: {
code: string;
codeType: EditorCodeType;
readOnly?: boolean;
openFindBox?: boolean;
fontZoomIn?: boolean;
fontZoomOut?: boolean;
onChange?: (code: string, language: EditorLangauge) => void;
onChange?: (code: string, codeType: EditorCodeType) => void;
hide?: boolean;
isDarkTheme?: boolean;
language: EditorLangauge;
}) {
const { code: templateCode, readOnly, openFindBox, fontZoomIn, fontZoomOut, isDarkTheme, language } = props;
const { code: templateCode, codeType, readOnly, openFindBox, fontZoomIn, fontZoomOut, isDarkTheme } = props;
const editor = useRef<Monaco.editor.IStandaloneCodeEditor | null>(null);
const [code, setCode] = useState(templateCode);

Expand Down Expand Up @@ -114,6 +114,11 @@ function EditorPanel(props: {
uri: 'https://raw.githubusercontent.com/gosling-lang/gosling.js/main/schema/gosling.schema.json',
fileMatch: ['*'],
schema: GoslingSchema
},
// TODO: How to support using either of schemas dynamically?
{
uri: 'https://raw.githubusercontent.com/gosling-lang/gosling.js/main/schema/gosling.schema.json',
schema: ThemeSchema
}
]
});
Expand All @@ -133,7 +138,7 @@ function EditorPanel(props: {

function onChangeHandle(newCode: string) {
setCode(newCode);
if (props.onChange) props.onChange(newCode, language);
if (props.onChange) props.onChange(newCode, codeType);
}

return (
Expand All @@ -147,7 +152,7 @@ function EditorPanel(props: {
></ReactResizeDetector>
<MonacoEditor
// Refer to https://github.com/react-monaco-editor/react-monaco-editor
language={language}
language={codeType === 'gosling-ts' ? 'typescript' : 'json'}
value={code}
theme={'gosling'}
options={{
Expand Down

0 comments on commit d5d6282

Please sign in to comment.